From c21e36e7f9b5091d085eaac5f472b19441e8bc92 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 14 Feb 2017 11:56:27 -0800 Subject: upgrade to MiMa 0.1.14 just on general dogfooding principle --- build.xml | 2 +- project/plugins.sbt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.xml b/build.xml index cfdff3f1e3..a37cced4cb 100644 --- a/build.xml +++ b/build.xml @@ -1656,7 +1656,7 @@ TODO: - + diff --git a/project/plugins.sbt b/project/plugins.sbt index 6001b6f2b4..3ec4f370c2 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -19,4 +19,4 @@ buildInfoKeys := Seq[BuildInfoKey](buildClasspath) buildInfoPackage := "scalabuild" -libraryDependencies += "com.typesafe" %% "mima-reporter" % "0.1.13" +libraryDependencies += "com.typesafe" %% "mima-reporter" % "0.1.14" -- cgit v1.2.3 From ac25524aa9e54c80baf49c6eaa1a84e4d8bf15a7 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Wed, 15 Feb 2017 14:36:59 -0800 Subject: More reusable path for windows job --- scripts/jobs/integrate/windows | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/jobs/integrate/windows b/scripts/jobs/integrate/windows index b823c1cdf9..2fb92ac261 100755 --- a/scripts/jobs/integrate/windows +++ b/scripts/jobs/integrate/windows @@ -4,9 +4,8 @@ export ANT_OPTS="-Dfile.encoding=UTF-8 -server -XX:+AggressiveOpts -XX:+UseParNewGC -Xmx2G -Xss1M -XX:MaxPermSize=512M -XX:ReservedCodeCacheSize=128M" -# TODO: don't hardcode this path -- should be in scala/scala-jenkins-infra -export PATH='/cygdrive/c/java/jdk-1.6/bin:/cygdrive/c/apache-ant-1.9.6/bin:/cygdrive/c/Program Files (x86)/Git-2.5.3/Cmd:/bin:/usr/bin:' -export JAVA_HOME='C:/java/jdk-1.6' +export JAVA_HOME="C:/java/jdk-1.6" +export PATH="$(cygpath $JAVA_HOME)/bin:$PATH" java -version javac -version -- cgit v1.2.3 From 2b7a79e965f71132f2ead6f25788d013fe99787c Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 15 Feb 2017 14:42:52 -0800 Subject: update Ant version info in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ed42eadaaa..bbfe7a797b 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ You need the following tools: - sbt, we recommend the [sbt-extras](https://github.com/paulp/sbt-extras) runner script. It provides sensible default jvm options (stack and heap size). - curl (for `./pull-binary-libs.sh`, used by the sbt / ant build). - - Apache Ant (version 1.9.3 or above) if you need to use the (deprecated) ant build. + - Apache Ant (version 1.9.x, minimum 1.9.3; Ant 1.10+ doesn't work on Java 6) if you are using the ant build. Mac OS X and Linux work. Windows may work if you use Cygwin. Community help with keeping the build working on Windows is appreciated. -- cgit v1.2.3 From 78d917393ea03ef94f892549f87cbc2cabba8ac6 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Thu, 23 Feb 2017 15:44:37 -0800 Subject: SI-10206 tighten fix for SI-6889 There are more supertypes of `AnyRef` than you might think: `?{def clone: ?}` is one example... --- .../scala/tools/nsc/typechecker/Implicits.scala | 41 ++++++++++++---------- test/files/neg/t6889.check | 7 ++-- test/files/neg/t6889.scala | 1 + 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 509ce59104..2333c29b30 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -134,11 +134,6 @@ trait Implicits { private val improvesCache = perRunCaches.newMap[(ImplicitInfo, ImplicitInfo), Boolean]() private val implicitSearchId = { var id = 1 ; () => try id finally id += 1 } - private def isInvalidConversionSource(tpe: Type): Boolean = tpe match { - case Function1(in, _) => in <:< NullClass.tpe - case _ => false - } - def resetImplicits() { implicitsCache.clear() infoMapCache.clear() @@ -1388,27 +1383,32 @@ trait Implicits { } } if (result.isSuccess && isView) { - def maybeInvalidConversionError(msg: String) { + def maybeInvalidConversionError(msg: String): Boolean = { // We have to check context.ambiguousErrors even though we are calling "issueAmbiguousError" // which ostensibly does exactly that before issuing the error. Why? I have no idea. Test is pos/t7690. // AM: I would guess it's because ambiguous errors will be buffered in silent mode if they are not reported if (context.ambiguousErrors) context.issueAmbiguousError(AmbiguousImplicitTypeError(tree, msg)) + true } pt match { - case Function1(_, out) => - // must inline to avoid capturing result - def prohibit(sym: Symbol) = (sym.tpe <:< out) && { - maybeInvalidConversionError(s"the result type of an implicit conversion must be more specific than ${sym.name}") - true - } - if (prohibit(AnyRefClass) || (settings.isScala211 && prohibit(AnyValClass))) - result = SearchFailure - case _ => false - } - if (settings.isScala211 && isInvalidConversionSource(pt)) { - maybeInvalidConversionError("an expression of type Null is ineligible for implicit conversion") - result = SearchFailure + // SI-10206 don't use subtyping to rule out AnyRef/AnyVal: + // - there are several valid structural types that are supertypes of AnyRef (e.g., created by HasMember); + // typeSymbol will do the trick (AnyRef is a type alias for Object), while ruling out these structural types + // - also don't want to accidentally constrain type vars through using <:< + case Function1(in, out) => + val outSym = out.typeSymbol + + val fail = + if (out.annotations.isEmpty && (outSym == ObjectClass || (isScala211 && outSym == AnyValClass))) + maybeInvalidConversionError(s"the result type of an implicit conversion must be more specific than $out") + else if (isScala211 && in.annotations.isEmpty && in.typeSymbol == NullClass) + maybeInvalidConversionError("an expression of type Null is ineligible for implicit conversion") + else false + + if (fail) result = SearchFailure + + case _ => } } @@ -1418,6 +1418,9 @@ trait Implicits { result } + // this setting is expensive to check, actually.... + private[this] val isScala211 = settings.isScala211 + def allImplicits: List[SearchResult] = { def search(iss: Infoss, isLocalToCallsite: Boolean) = applicableInfos(iss, isLocalToCallsite).values ( diff --git a/test/files/neg/t6889.check b/test/files/neg/t6889.check index a77e8a010c..c14c3b09c0 100644 --- a/test/files/neg/t6889.check +++ b/test/files/neg/t6889.check @@ -1,7 +1,10 @@ t6889.scala:16: error: the result type of an implicit conversion must be more specific than AnyRef def f(x: Dingo): AnyRef = x // fail - no conversion to AnyRef ^ -t6889.scala:17: error: an expression of type Null is ineligible for implicit conversion +t6889.scala:17: error: the result type of an implicit conversion must be more specific than Object + def f2(x: Dingo): Object = x // fail - no conversion to Object + ^ +t6889.scala:18: error: an expression of type Null is ineligible for implicit conversion var x: Int = null // fail - no conversion from Null ^ -two errors found +three errors found diff --git a/test/files/neg/t6889.scala b/test/files/neg/t6889.scala index ef1963669c..3fc235bf7e 100644 --- a/test/files/neg/t6889.scala +++ b/test/files/neg/t6889.scala @@ -14,5 +14,6 @@ object Test { trait Dingo extends Any with bippy.Bippy[foo.unrelated.Unrelated] def f(x: Dingo): AnyRef = x // fail - no conversion to AnyRef + def f2(x: Dingo): Object = x // fail - no conversion to Object var x: Int = null // fail - no conversion from Null } -- cgit v1.2.3 From 894b027ddf1551317ecdbda053aec90b6d6fa2f4 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Sun, 26 Feb 2017 16:01:37 -0800 Subject: Allow user-defined `[un]apply` in case companion Don't emit a synthetic `apply` (or `unapply`) when it would clash with an existing one. This allows e.g., a `private apply`, along with a `case class` with a `private` constructor. We have to retract the synthetic method in a pretty roundabout way, as we need the other methods and the owner to be completed already. Unless we have to complete the synthetic `apply` while completing the user-defined one, this should not be a problem. If this does happen, this implies there's a cycle in computing the user-defined signature and the synthetic one, which is not allowed. --- .../scala/tools/nsc/typechecker/Namers.scala | 81 ++++++++++++++++++---- test/files/neg/userdefined_apply.check | 13 ++++ test/files/neg/userdefined_apply.scala | 31 +++++++++ test/files/pos/userdefined_apply.scala | 36 ++++++++++ 4 files changed, 149 insertions(+), 12 deletions(-) create mode 100644 test/files/neg/userdefined_apply.check create mode 100644 test/files/neg/userdefined_apply.scala create mode 100644 test/files/pos/userdefined_apply.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index ee64a6646f..19607b6681 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -610,7 +610,15 @@ trait Namers extends MethodSynthesis { noDuplicates(selectors map (_.rename), AppearsTwice) } - def enterCopyMethod(copyDef: DefDef): Symbol = { + class CompleterWrapper(completer: TypeCompleter) extends TypeCompleter { + val tree = completer.tree + + override def complete(sym: Symbol): Unit = { + completer.complete(sym) + } + } + + def copyMethodCompleter(copyDef: DefDef): TypeCompleter = { val sym = copyDef.symbol val lazyType = completerOf(copyDef) @@ -629,14 +637,57 @@ trait Namers extends MethodSynthesis { ) } - sym setInfo { - mkTypeCompleter(copyDef) { sym => - assignParamTypes() - lazyType complete sym - } + mkTypeCompleter(copyDef) { sym => + assignParamTypes() + lazyType complete sym } } + // for apply/unapply, which may need to disappear when they clash with a user-defined method of matching signature + def applyUnapplyMethodCompleter(un_applyDef: DefDef, companionContext: Context): TypeCompleter = + new CompleterWrapper(completerOf(un_applyDef)) { + override def complete(sym: Symbol): Unit = { + super.complete(sym) + + // If there's a same-named locked symbol, we're currently completing its signature. + // This means it (may) refer to us, and is thus either overloaded or recursive without a signature. + // rule out locked symbols from the owner.info.member call + val scopePartiallyCompleted = + companionContext.scope.lookupAll(sym.name).exists(existing => existing != sym && existing.hasFlag(LOCKED)) + + val suppress = + scopePartiallyCompleted || { + val userDefined = companionContext.owner.info.member(sym.name).filter(_ != sym) + (userDefined != NoSymbol) && { + userDefined.info match { + // TODO: do we have something for this already? the synthetic symbol can't be overloaded, right? + case OverloadedType(pre, alternatives) => + // pre probably relevant because of inherited overloads? + alternatives.exists(_.isErroneous) || alternatives.exists(alt => pre.memberInfo(alt) matches pre.memberInfo(sym)) + case tp => + (tp eq ErrorType) || tp.matches(sym.info) + } + } + } + + if (suppress) { + sym setInfo ErrorType + sym setFlag IS_ERROR + + // Don't unlink in an error situation to generate less confusing error messages. + // Ideally, our error reporting would distinguish overloaded from recursive user-defined apply methods without signature, + // but this would require some form of partial-completion of method signatures, so that we can + // know what the argument types were, even though we can't complete the result type, because + // we hit a cycle while trying to compute it (when we get here with locked user-defined symbols, we + // are in the complete for that symbol, and thus the locked symbol has not yet received enough info; + // I hesitate to provide more info, because it would involve a WildCard or something for its result type, + // which could upset other code paths) + if (!scopePartiallyCompleted) + companionContext.scope.unlink(sym) + } + } + } + def completerOf(tree: Tree): TypeCompleter = { val mono = namerOf(tree.symbol) monoTypeCompleter tree val tparams = treeInfo.typeParameters(tree) @@ -697,11 +748,17 @@ trait Namers extends MethodSynthesis { val bridgeFlag = if (mods hasAnnotationNamed tpnme.bridgeAnnot) BRIDGE | ARTIFACT else 0 val sym = assignAndEnterSymbol(tree) setFlag bridgeFlag - if (name == nme.copy && sym.isSynthetic) - enterCopyMethod(tree) - else - sym setInfo completerOf(tree) - } + // copy/apply/unapply synthetics are added using the addIfMissing mechanism, + // which ensures the owner has its preliminary info (we may add another decl here) + val completer = + if (sym hasFlag SYNTHETIC) { + if (name == nme.copy) copyMethodCompleter(tree) + else if (sym hasFlag CASE) applyUnapplyMethodCompleter(tree, context) + else completerOf(tree) + } else completerOf(tree) + + sym setInfo completer + } def enterClassDef(tree: ClassDef) { val ClassDef(mods, _, _, impl) = tree @@ -1351,7 +1408,7 @@ trait Namers extends MethodSynthesis { val defTpt = // don't mess with tpt's of case copy default getters, because assigning something other than TypeTree() - // will break the carefully orchestrated naming/typing logic that involves enterCopyMethod and caseClassCopyMeth + // will break the carefully orchestrated naming/typing logic that involves copyMethodCompleter and caseClassCopyMeth if (meth.isCaseCopy) TypeTree() else { // If the parameter type mentions any type parameter of the method, let the compiler infer the diff --git a/test/files/neg/userdefined_apply.check b/test/files/neg/userdefined_apply.check new file mode 100644 index 0000000000..ca0154885d --- /dev/null +++ b/test/files/neg/userdefined_apply.check @@ -0,0 +1,13 @@ +userdefined_apply.scala:3: error: overloaded method apply needs result type + private def apply(x: Int) = if (x > 0) new ClashOverloadNoSig(x) else apply("") + ^ +userdefined_apply.scala:12: error: overloaded method apply needs result type + private def apply(x: Int) = if (x > 0) ClashRecNoSig(1) else ??? + ^ +userdefined_apply.scala:19: error: overloaded method apply needs result type + private def apply(x: Boolean) = if (x) NoClashNoSig(1) else ??? + ^ +userdefined_apply.scala:26: error: overloaded method apply needs result type + private def apply(x: Boolean) = if (x) NoClashOverload(1) else apply("") + ^ +four errors found diff --git a/test/files/neg/userdefined_apply.scala b/test/files/neg/userdefined_apply.scala new file mode 100644 index 0000000000..1f2aff6e82 --- /dev/null +++ b/test/files/neg/userdefined_apply.scala @@ -0,0 +1,31 @@ +object ClashOverloadNoSig { + // error: overloaded method apply needs result type + private def apply(x: Int) = if (x > 0) new ClashOverloadNoSig(x) else apply("") + + def apply(x: String): ClashOverloadNoSig = ??? +} + +case class ClashOverloadNoSig private(x: Int) + +object ClashRecNoSig { + // error: recursive method apply needs result type + private def apply(x: Int) = if (x > 0) ClashRecNoSig(1) else ??? +} + +case class ClashRecNoSig private(x: Int) + +object NoClashNoSig { + // error: overloaded method apply needs result type + private def apply(x: Boolean) = if (x) NoClashNoSig(1) else ??? +} + +case class NoClashNoSig private(x: Int) + +object NoClashOverload { + // error: overloaded method apply needs result type + private def apply(x: Boolean) = if (x) NoClashOverload(1) else apply("") + + def apply(x: String): NoClashOverload = ??? +} + +case class NoClashOverload private(x: Int) diff --git a/test/files/pos/userdefined_apply.scala b/test/files/pos/userdefined_apply.scala new file mode 100644 index 0000000000..ca563f1dc5 --- /dev/null +++ b/test/files/pos/userdefined_apply.scala @@ -0,0 +1,36 @@ +// NOTE: the companion inherits a public apply method from Function1! +case class NeedsCompanion private (x: Int) + +object ClashNoSig { // ok + private def apply(x: Int) = if (x > 0) new ClashNoSig(x) else ??? +} +case class ClashNoSig private (x: Int) + + +object Clash { + private def apply(x: Int) = if (x > 0) new Clash(x) else ??? +} +case class Clash private (x: Int) + +object ClashSig { + private def apply(x: Int): ClashSig = if (x > 0) new ClashSig(x) else ??? +} +case class ClashSig private (x: Int) + +object ClashOverload { + private def apply(x: Int): ClashOverload = if (x > 0) new ClashOverload(x) else apply("") + def apply(x: String): ClashOverload = ??? +} +case class ClashOverload private (x: Int) + +object NoClashSig { + private def apply(x: Boolean): NoClashSig = if (x) NoClashSig(1) else ??? +} +case class NoClashSig private (x: Int) + +object NoClashOverload { + // needs full sig + private def apply(x: Boolean): NoClashOverload = if (x) NoClashOverload(1) else apply("") + def apply(x: String): NoClashOverload = ??? +} +case class NoClashOverload private (x: Int) -- cgit v1.2.3 From 575a668a38014f25cb4930ef2b1991a861ba558a Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 28 Feb 2017 10:24:45 -0800 Subject: Clarify spec of interaction of existing vs synthetic apply/unapply When matching user-defined apply/unapply members exist in a case class's companion object, don't add clashing synthetic ones. --- spec/05-classes-and-objects.md | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/spec/05-classes-and-objects.md b/spec/05-classes-and-objects.md index 69828ec7fe..82f399fe47 100644 --- a/spec/05-classes-and-objects.md +++ b/spec/05-classes-and-objects.md @@ -851,9 +851,8 @@ already a `val` or `var` modifier. Hence, an accessor definition for the parameter is [generated](#class-definitions). A case class definition of `$c$[$\mathit{tps}\,$]($\mathit{ps}_1\,$)$\ldots$($\mathit{ps}_n$)` with type -parameters $\mathit{tps}$ and value parameters $\mathit{ps}$ implicitly -generates an [extractor object](08-pattern-matching.html#extractor-patterns) which is -defined as follows: +parameters $\mathit{tps}$ and value parameters $\mathit{ps}$ implies +the definition of a companion object, which serves as an [extractor object](08-pattern-matching.html#extractor-patterns). It has the following shape: ```scala object $c$ { @@ -870,11 +869,14 @@ each $\mathit{xs}\_i$ denotes the parameter names of the parameter section $\mathit{ps}\_i$, and $\mathit{xs}\_{11}, \ldots , \mathit{xs}\_{1k}$ denote the names of all parameters in the first parameter section $\mathit{xs}\_1$. -If a type parameter section is missing in the -class, it is also missing in the `apply` and -`unapply` methods. -The definition of `apply` is omitted if class $c$ is -`abstract`. +If a type parameter section is missing in the class, it is also missing in the `apply` and `unapply` methods. + +If the companion object $c$ is already defined, +the `apply` and `unapply` methods are added to the existing object. +The definition of `apply` is omitted if class $c$ is `abstract`. +If the object $c$ already defines a [matching](#definition-matching) member of the +same name as the synthetic member to be added, the synthetic member +is not added (overloading or mutual recursion is allowed, however). If the case class definition contains an empty value parameter list, the `unapply` method returns a `Boolean` instead of an `Option` type and @@ -887,9 +889,6 @@ def unapply[$\mathit{tps}\,$]($x$: $c$[$\mathit{tps}\,$]) = x ne null The name of the `unapply` method is changed to `unapplySeq` if the first parameter section $\mathit{ps}_1$ of $c$ ends in a [repeated parameter](04-basic-declarations-and-definitions.html#repeated-parameters). -If a companion object $c$ exists already, no new object is created, -but the `apply` and `unapply` methods are added to the existing -object instead. A method named `copy` is implicitly added to every case class unless the class already has a member (directly defined or inherited) with that name, or the -- cgit v1.2.3 From 615849058b5452b9d54ac152a1380ca7f81998c9 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 28 Feb 2017 14:14:11 -0800 Subject: Improvements based on reviews by Lukas & Jason --- spec/05-classes-and-objects.md | 5 +-- .../scala/tools/nsc/typechecker/Namers.scala | 48 ++++++++++++++-------- .../scala/reflect/internal/tpe/FindMembers.scala | 14 +++++++ test/files/neg/userdefined_apply.check | 20 +++++++-- test/files/neg/userdefined_apply.scala | 26 ++++++++++++ test/files/pos/userdefined_apply.scala | 18 ++++++++ 6 files changed, 107 insertions(+), 24 deletions(-) diff --git a/spec/05-classes-and-objects.md b/spec/05-classes-and-objects.md index 82f399fe47..65666e31cb 100644 --- a/spec/05-classes-and-objects.md +++ b/spec/05-classes-and-objects.md @@ -873,10 +873,9 @@ If a type parameter section is missing in the class, it is also missing in the ` If the companion object $c$ is already defined, the `apply` and `unapply` methods are added to the existing object. +If the object $c$ already has a [matching](#definition-matching) +`apply` (or `unapply`) member, no new definition is added. The definition of `apply` is omitted if class $c$ is `abstract`. -If the object $c$ already defines a [matching](#definition-matching) member of the -same name as the synthetic member to be added, the synthetic member -is not added (overloading or mutual recursion is allowed, however). If the case class definition contains an empty value parameter list, the `unapply` method returns a `Boolean` instead of an `Option` type and diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 19607b6681..69b8cb12e6 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -647,25 +647,41 @@ trait Namers extends MethodSynthesis { def applyUnapplyMethodCompleter(un_applyDef: DefDef, companionContext: Context): TypeCompleter = new CompleterWrapper(completerOf(un_applyDef)) { override def complete(sym: Symbol): Unit = { + assert(sym hasAllFlags CASE | SYNTHETIC, sym.defString) + super.complete(sym) + // owner won't be locked + val ownerInfo = companionContext.owner.info + // If there's a same-named locked symbol, we're currently completing its signature. - // This means it (may) refer to us, and is thus either overloaded or recursive without a signature. - // rule out locked symbols from the owner.info.member call - val scopePartiallyCompleted = - companionContext.scope.lookupAll(sym.name).exists(existing => existing != sym && existing.hasFlag(LOCKED)) - - val suppress = - scopePartiallyCompleted || { - val userDefined = companionContext.owner.info.member(sym.name).filter(_ != sym) + // If `scopePartiallyCompleted`, the program is known to have a type error, since + // this means a user-defined method is missing a result type while its rhs refers to `sym` or an overload. + // This is an error because overloaded/recursive methods must have a result type. + // The method would be overloaded if its signature, once completed, would not match the synthetic method's, + // or recursive if it turned out we should unlink our synthetic method (matching sig). + // In any case, error out. We don't unlink the symbol so that `symWasOverloaded` says yes, + // which would be wrong if the method is in fact recursive, but it seems less confusing. + val scopePartiallyCompleted = new HasMember(ownerInfo, sym.name, BridgeFlags | SYNTHETIC, LOCKED).apply() + + // Check `scopePartiallyCompleted` first to rule out locked symbols from the owner.info.member call, + // as FindMember will call info on a locked symbol (while checking type matching to assemble an overloaded type), + // and throw a TypeError, so that we are aborted. + // Do not consider deferred symbols, as suppressing our concrete implementation would be an error regardless + // of whether the signature matches (if it matches, we omitted a valid implementation, if it doesn't, + // we would get an error for the missing implementation it isn't implemented by some overload other than our synthetic one) + val suppress = scopePartiallyCompleted || { + // can't exclude deferred members using DEFERRED flag here (TODO: why?) + val userDefined = ownerInfo.memberBasedOnName(sym.name, BridgeFlags | SYNTHETIC) + (userDefined != NoSymbol) && { - userDefined.info match { - // TODO: do we have something for this already? the synthetic symbol can't be overloaded, right? - case OverloadedType(pre, alternatives) => - // pre probably relevant because of inherited overloads? - alternatives.exists(_.isErroneous) || alternatives.exists(alt => pre.memberInfo(alt) matches pre.memberInfo(sym)) - case tp => - (tp eq ErrorType) || tp.matches(sym.info) + assert(userDefined != sym) + val alts = userDefined.alternatives // could be just the one, if this member isn't overloaded + // don't compute any further `memberInfo`s if there's an error somewhere + alts.exists(_.isErroneous) || { + val self = companionContext.owner.thisType + val memberInfo = self.memberInfo(sym) + alts.exists(alt => !alt.isDeferred && (self.memberInfo(alt) matches memberInfo)) } } } @@ -748,8 +764,6 @@ trait Namers extends MethodSynthesis { val bridgeFlag = if (mods hasAnnotationNamed tpnme.bridgeAnnot) BRIDGE | ARTIFACT else 0 val sym = assignAndEnterSymbol(tree) setFlag bridgeFlag - // copy/apply/unapply synthetics are added using the addIfMissing mechanism, - // which ensures the owner has its preliminary info (we may add another decl here) val completer = if (sym hasFlag SYNTHETIC) { if (name == nme.copy) copyMethodCompleter(tree) diff --git a/src/reflect/scala/reflect/internal/tpe/FindMembers.scala b/src/reflect/scala/reflect/internal/tpe/FindMembers.scala index 83a5d23e7c..1b00815bca 100644 --- a/src/reflect/scala/reflect/internal/tpe/FindMembers.scala +++ b/src/reflect/scala/reflect/internal/tpe/FindMembers.scala @@ -285,4 +285,18 @@ trait FindMembers { initBaseClasses.head.newOverloaded(tpe, members) } } + + private[scala] final class HasMember(tpe: Type, name: Name, excludedFlags: Long, requiredFlags: Long) extends FindMemberBase[Boolean](tpe, name, excludedFlags, requiredFlags) { + private[this] var _result = false + override protected def result: Boolean = _result + + protected def shortCircuit(sym: Symbol): Boolean = { + _result = true + true // prevents call to addMemberIfNew + } + + // Not used + protected def addMemberIfNew(sym: Symbol): Unit = {} + } + } diff --git a/test/files/neg/userdefined_apply.check b/test/files/neg/userdefined_apply.check index ca0154885d..c8c8976f5f 100644 --- a/test/files/neg/userdefined_apply.check +++ b/test/files/neg/userdefined_apply.check @@ -1,13 +1,25 @@ userdefined_apply.scala:3: error: overloaded method apply needs result type private def apply(x: Int) = if (x > 0) new ClashOverloadNoSig(x) else apply("") ^ -userdefined_apply.scala:12: error: overloaded method apply needs result type +userdefined_apply.scala:14: error: overloaded method apply needs result type private def apply(x: Int) = if (x > 0) ClashRecNoSig(1) else ??? ^ -userdefined_apply.scala:19: error: overloaded method apply needs result type +userdefined_apply.scala:21: error: overloaded method apply needs result type private def apply(x: Boolean) = if (x) NoClashNoSig(1) else ??? ^ -userdefined_apply.scala:26: error: overloaded method apply needs result type +userdefined_apply.scala:28: error: overloaded method apply needs result type private def apply(x: Boolean) = if (x) NoClashOverload(1) else apply("") ^ -four errors found +userdefined_apply.scala:45: error: recursive method apply needs result type +case class NoClashNoSigPoly private(x: Int) + ^ +userdefined_apply.scala:39: error: NoClashNoSigPoly.type does not take parameters + def apply(x: T) = if (???) NoClashNoSigPoly(1) else ??? + ^ +userdefined_apply.scala:57: error: recursive method apply needs result type +case class ClashNoSigPoly private(x: Int) + ^ +userdefined_apply.scala:51: error: ClashNoSigPoly.type does not take parameters + def apply(x: T) = if (???) ClashNoSigPoly(1) else ??? + ^ +8 errors found diff --git a/test/files/neg/userdefined_apply.scala b/test/files/neg/userdefined_apply.scala index 1f2aff6e82..0a0d960b39 100644 --- a/test/files/neg/userdefined_apply.scala +++ b/test/files/neg/userdefined_apply.scala @@ -8,6 +8,8 @@ object ClashOverloadNoSig { case class ClashOverloadNoSig private(x: Int) object ClashRecNoSig { + // TODO: status quo is that the error refers to an overloaded method, which is actually recursive + // (we should have unlinked the symbol in the `if(suppress)` part of `applyUnapplyMethodCompleter`) // error: recursive method apply needs result type private def apply(x: Int) = if (x > 0) ClashRecNoSig(1) else ??? } @@ -29,3 +31,27 @@ object NoClashOverload { } case class NoClashOverload private(x: Int) + + +class BaseNCNSP[T] { + // TODO: suppress the following error + // error: NoClashNoSigPoly.type does not take parameters + def apply(x: T) = if (???) NoClashNoSigPoly(1) else ??? +} + +object NoClashNoSigPoly extends BaseNCNSP[Boolean] +// TODO: position error at definition of apply in superclass instead of on case clss +// error: recursive method apply needs result type +case class NoClashNoSigPoly private(x: Int) + + +class BaseCNSP[T] { + // TODO: suppress the following error + // error: ClashNoSigPoly.type does not take parameters + def apply(x: T) = if (???) ClashNoSigPoly(1) else ??? +} + +object ClashNoSigPoly extends BaseCNSP[Int] +// TODO: position error at definition of apply in superclass instead of on case clss +// error: recursive method apply needs result type +case class ClashNoSigPoly private(x: Int) diff --git a/test/files/pos/userdefined_apply.scala b/test/files/pos/userdefined_apply.scala index ca563f1dc5..e29f9f5141 100644 --- a/test/files/pos/userdefined_apply.scala +++ b/test/files/pos/userdefined_apply.scala @@ -34,3 +34,21 @@ object NoClashOverload { def apply(x: String): NoClashOverload = ??? } case class NoClashOverload private (x: Int) + + + +class BaseNCP[T] { + // error: overloaded method apply needs result type + def apply(x: T): NoClashPoly = if (???) NoClashPoly(1) else ??? +} + +object NoClashPoly extends BaseNCP[Boolean] +case class NoClashPoly private(x: Int) + + +class BaseCP[T] { + // error: overloaded method apply needs result type + def apply(x: T): ClashPoly = if (???) ClashPoly(1) else ??? +} +object ClashPoly extends BaseCP[Int] +case class ClashPoly private(x: Int) -- cgit v1.2.3 From c2c37acd928f9b8f8a1d208ee9ee6135b54a1fcd Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Thu, 2 Mar 2017 21:26:55 +0100 Subject: bump copyright year to 2017 --- build.xml | 2 +- doc/LICENSE.md | 4 ++-- doc/License.rtf | 4 ++-- project/VersionUtil.scala | 2 +- src/library/scala/util/Properties.scala | 2 +- src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala | 2 +- src/scalap/decoder.properties | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build.xml b/build.xml index a37cced4cb..f8c0380f41 100644 --- a/build.xml +++ b/build.xml @@ -184,7 +184,7 @@ TODO: - + diff --git a/doc/LICENSE.md b/doc/LICENSE.md index c56b38daa2..ce29d7e7d4 100644 --- a/doc/LICENSE.md +++ b/doc/LICENSE.md @@ -2,9 +2,9 @@ Scala is licensed under the [BSD 3-Clause License](http://opensource.org/license ## Scala License -Copyright (c) 2002-2016 EPFL +Copyright (c) 2002-2017 EPFL -Copyright (c) 2011-2016 Lightbend, Inc. +Copyright (c) 2011-2017 Lightbend, Inc. All rights reserved. diff --git a/doc/License.rtf b/doc/License.rtf index c8f24838a2..adc7dfdcb8 100644 --- a/doc/License.rtf +++ b/doc/License.rtf @@ -10,8 +10,8 @@ \fs48 Scala License \fs40 \ -\fs26 Copyright (c) 2002-2016 EPFL\ -Copyright (c) 2011-2016 Lightbend, Inc.\ +\fs26 Copyright (c) 2002-2017 EPFL\ +Copyright (c) 2011-2017 Lightbend, Inc.\ All rights reserved.\ \ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\ diff --git a/project/VersionUtil.scala b/project/VersionUtil.scala index 4705bbb6ce..2a52159d4e 100644 --- a/project/VersionUtil.scala +++ b/project/VersionUtil.scala @@ -18,7 +18,7 @@ object VersionUtil { ) lazy val generatePropertiesFileSettings = Seq[Setting[_]]( - copyrightString := "Copyright 2002-2016, LAMP/EPFL", + copyrightString := "Copyright 2002-2017, LAMP/EPFL and Lightbend, Inc.", resourceGenerators in Compile += generateVersionPropertiesFile.map(file => Seq(file)).taskValue, generateVersionPropertiesFile := generateVersionPropertiesFileImpl.value ) diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala index 7ea597eac9..416aeeccb3 100644 --- a/src/library/scala/util/Properties.scala +++ b/src/library/scala/util/Properties.scala @@ -105,7 +105,7 @@ private[scala] trait PropertiesTrait { * or "version (unknown)" if it cannot be determined. */ val versionString = "version " + scalaPropOrElse("version.number", "(unknown)") - val copyrightString = scalaPropOrElse("copyright.string", "Copyright 2002-2016, LAMP/EPFL") + val copyrightString = scalaPropOrElse("copyright.string", "Copyright 2002-2017, LAMP/EPFL and Lightbend, Inc.") /** This is the encoding to use reading in source files, overridden with -encoding. * Note that it uses "prop" i.e. looks in the scala jar, not the system properties. diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala index f70bac8f83..08d3508a78 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala @@ -280,7 +280,7 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp { if (Set("epfl", "EPFL").contains(tpl.universe.settings.docfooter.value)) - + else } diff --git a/src/scalap/decoder.properties b/src/scalap/decoder.properties index 9bb8d130ea..0bff4c81d4 100644 --- a/src/scalap/decoder.properties +++ b/src/scalap/decoder.properties @@ -1,2 +1,2 @@ version.number=2.0.1 -copyright.string=(c) 2002-2016 LAMP/EPFL +copyright.string=(c) 2002-2017 LAMP/EPFL -- cgit v1.2.3 From 849d09b9e10d025df7f91494315f927f68bc9dd6 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 24 Feb 2017 09:37:20 +1000 Subject: Test case for SI-10206 Implicit search implements a restriction that the target type for an implicit view should be more specific that AnyRef or AnyVal. scala> def foo(s: String): AnyVal = s :12: error: the result type of an implicit conversion must be more specific than AnyVal def foo(s: String): AnyVal = s ^ Without this, an implicit value classes over `String` would be applied, which is unlikely to be what was intended. Implicit views are implemented as an implicit search for a function type with a structural type as its result. This structural type is created with: scala> val schema = analyzer.HasMethodMatching.apply(TermName("clone"), Nil, WildcardType) schema: $r.intp.global.analyzer.global.Type = ?{def clone(): ?} The quirk arises when, as above, we're seeking a member with the same name as a member of AnyRef. AnyRef is seen to be a subtype of the result type: scala> AnyRefClass.tpe <:< schema res23: Boolean = true Which leads to the implicit in the test case being disqualified. The typer opts to report the error about the inapplicability of the inherited clone method, so we don't even know why the implicit was discarded. --- test/files/pos/t10206.scala | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 test/files/pos/t10206.scala diff --git a/test/files/pos/t10206.scala b/test/files/pos/t10206.scala new file mode 100644 index 0000000000..3ddd1ea2fd --- /dev/null +++ b/test/files/pos/t10206.scala @@ -0,0 +1,15 @@ +class Foo(val bar: String) + +object Foo { + implicit class Enrich(foo: Foo) { + def clone(x: Int, y: Int): Int = x + y + } +} + +object Main extends App { + val foo = new Foo("hello") + println(foo.clone(1, 2)) // <- does not compile + // the implicit view was being disqualified because a new check in the compiler + // that implicit views must not target Any or AnyRef considered an implicit search + // for `foo.type => ?{def clone: ?}` to targeted AnyRef. +} -- cgit v1.2.3 From 42f813e18160b6ea8dfc9c2ae850a67dd0819773 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 3 Mar 2017 17:48:24 +0100 Subject: [backport] new repo, version numbers for integration builds Integration builds now have version number like `2.12.2-bin-sha7` or `2.13.0-pre-sha7` and are published to scala-integration (no longer scala-release-temp). scala-release-temp is still used in the bootstrap script for publishing locker. --- README.md | 2 +- project/VersionUtil.scala | 35 ++++-- scripts/jobs/integrate/bootstrap | 136 ++++++++++++--------- .../scala/tools/nsc/settings/ScalaVersion.scala | 2 +- 4 files changed, 103 insertions(+), 72 deletions(-) diff --git a/README.md b/README.md index bbfe7a797b..c2891390d4 100644 --- a/README.md +++ b/README.md @@ -230,7 +230,7 @@ tested version during CI validation. The Scala CI builds nightly download releases (including all modules) and publishes them to the following locations: - [2.12.x](http://www.scala-lang.org/files/archive/nightly/2.12.x/?C=M;O=D) - - [2.11.x](http://www.scala-lang.org/files/archive/nightly/2.11.x/?C=M;O=A) + - [2.11.x](http://www.scala-lang.org/files/archive/nightly/2.11.x/?C=M;O=D) The CI also publishes nightly API docs: - [2.12.x](http://www.scala-lang.org/files/archive/nightly/2.12.x/api/?C=M;O=D) diff --git a/project/VersionUtil.scala b/project/VersionUtil.scala index 2a52159d4e..3f9b727ef0 100644 --- a/project/VersionUtil.scala +++ b/project/VersionUtil.scala @@ -45,17 +45,19 @@ object VersionUtil { /** Compute the canonical, Maven and OSGi version number from `baseVersion` and `baseVersionSuffix`. * Examples of the generated versions: * - * ("2.11.8", "SNAPSHOT" ) -> ("2.11.8-20151215-133023-7559aed3c5", "2.11.8-SNAPSHOT", "2.11.8.v20151215-133023-7559aed3c5") - * ("2.11.8", "SHA-SNAPSHOT") -> ("2.11.8-20151215-133023-7559aed3c5", "2.11.8-7559aed3c5-SNAPSHOT", "2.11.8.v20151215-133023-7559aed3c5") - * ("2.11.8", "" ) -> ("2.11.8", "2.11.8", "2.11.8.v20151215-133023-VFINAL-7559aed3c5") - * ("2.11.8", "M3" ) -> ("2.11.8-M3", "2.11.8-M3", "2.11.8.v20151215-133023-M3-7559aed3c5") - * ("2.11.8", "RC4" ) -> ("2.11.8-RC4", "2.11.8-RC4", "2.11.8.v20151215-133023-RC4-7559aed3c5") - * ("2.11.8-RC4", "SPLIT" ) -> ("2.11.8-RC4", "2.11.8-RC4", "2.11.8.v20151215-133023-RC4-7559aed3c5") + * ("2.11.8", "SNAPSHOT" ) -> ("2.11.8-20151215-133023-7559aed", "2.11.8-bin-SNAPSHOT", "2.11.8.v20151215-133023-7559aed") + * ("2.11.8", "SHA-SNAPSHOT") -> ("2.11.8-20151215-133023-7559aed", "2.11.8-bin-7559aed-SNAPSHOT", "2.11.8.v20151215-133023-7559aed") + * ("2.11.8", "SHA" ) -> ("2.11.8-7559aed", "2.11.8-bin-7559aed", "2.11.8.v20151215-133023-7559aed") + * ("2.11.0", "SHA" ) -> ("2.11.0-7559aed", "2.11.0-pre-7559aed", "2.11.0.v20151215-133023-7559aed") + * ("2.11.8", "" ) -> ("2.11.8", "2.11.8", "2.11.8.v20151215-133023-VFINAL-7559aed") + * ("2.11.8", "M3" ) -> ("2.11.8-M3", "2.11.8-M3", "2.11.8.v20151215-133023-M3-7559aed") + * ("2.11.8", "RC4" ) -> ("2.11.8-RC4", "2.11.8-RC4", "2.11.8.v20151215-133023-RC4-7559aed") + * ("2.11.8-RC4", "SPLIT" ) -> ("2.11.8-RC4", "2.11.8-RC4", "2.11.8.v20151215-133023-RC4-7559aed") * * A `baseVersionSuffix` of "SNAPSHOT" is the default, which is used for local snapshot builds. The PR validation - * job uses "SHA-SNAPSHOT". An empty suffix is used for releases. All other suffix values are treated as RC / - * milestone builds. The special suffix value "SPLIT" is used to split the real suffix off from `baseVersion` - * instead and then apply the usual logic. */ + * job uses "SHA-SNAPSHOT". A proper version number for an integration build can be computed with "SHA". An empty + * suffix is used for releases. All other suffix values are treated as RC / milestone builds. The special suffix + * value "SPLIT" is used to split the real suffix off from `baseVersion` instead and then apply the usual logic. */ private lazy val versionPropertiesImpl: Def.Initialize[Versions] = Def.setting { val (base, suffix) = { @@ -78,11 +80,18 @@ object VersionUtil { val date = executeTool("get-scala-commit-date") val sha = executeTool("get-scala-commit-sha").substring(0, 7) // The script produces 10 digits at the moment + val Patch = """\d+\.\d+\.(\d+)""".r + def cross = base match { + case Patch(p) if p.toInt > 0 => "bin" + case _ => "pre" + } + val (canonicalV, mavenV, osgiV, release) = suffix match { - case "SNAPSHOT" => (s"$base-$date-$sha", s"$base-SNAPSHOT", s"$base.v$date-$sha", false) - case "SHA-SNAPSHOT" => (s"$base-$date-$sha", s"$base-$sha-SNAPSHOT", s"$base.v$date-$sha", false) - case "" => (s"$base", s"$base", s"$base.v$date-VFINAL-$sha", true) - case suffix => (s"$base-$suffix", s"$base-$suffix", s"$base.v$date-$suffix-$sha", true) + case "SNAPSHOT" => (s"$base-$date-$sha", s"$base-$cross-SNAPSHOT", s"$base.v$date-$sha", false) + case "SHA-SNAPSHOT" => (s"$base-$date-$sha", s"$base-$cross-$sha-SNAPSHOT", s"$base.v$date-$sha", false) + case "SHA" => (s"$base-$sha", s"$base-$cross-$sha", s"$base.v$date-$sha", false) + case "" => (s"$base", s"$base", s"$base.v$date-VFINAL-$sha", true) + case suffix => (s"$base-$suffix", s"$base-$suffix", s"$base.v$date-$suffix-$sha", true) } Versions(canonicalV, mavenV, osgiV, sha, date, release) diff --git a/scripts/jobs/integrate/bootstrap b/scripts/jobs/integrate/bootstrap index abb5b283c6..216a93637b 100644 --- a/scripts/jobs/integrate/bootstrap +++ b/scripts/jobs/integrate/bootstrap @@ -3,16 +3,17 @@ # Script Overview # - determine scala version # - determine module versions -# - build minimal core (aka locker) of Scala, use the determined version number, publish to private-repo -# - build those modules where a binary compatible version doesn't exist, publish to private-repo -# - build Scala using the previously built core and bootstrap modules, publish to private-repo (overwrites the minimal core version on private-repo) -# - for releases (not nightlies) +# - build minimal core (aka locker) of Scala, use the determined version number, publish to scala-integration +# - build those modules where a binary compatible version doesn't exist, publish to scala-integration +# - build Scala using the previously built core and bootstrap modules, publish to scala-integration, overwriting +# the existing artifacts (note: in 2.12.x we use scala-release-temp for locker, but that doesn't work in 2.11.x, +# because we can only pass in one `extra.repo` to ant, see comment in PR 5764). +# - for releases # - stage Scala on sonatype # - rebuild modules that needed a rebuild with this Scala build, and stage them on sonatype # - for nightlies # - force rebuild all modules and publish them locally (for testing purposes) # - the Scala version is serialized to jenkins.properties, which is passed downstream to scala-release jobs -# - this removes the need to tag scala/scala-dist (it's still encouraged for releases, but not a hard requirement) # Specifying the Scala version: @@ -23,8 +24,8 @@ # - Note: After building a release, the jenkins job provides an updated versions.properties file as artifact. # Put this file in the Scala repo and create a pull request, and also update the file build.number. # -# - Otherwise, a nightly release is built: -# - version number is read from the build.number file, extended with -$sha-nightly +# - Otherwise, an integration build is performed: +# - version number is read from the build.number file, extended with -[bin|pre]-$sha # Specifying module versions: there are two modes @@ -56,7 +57,7 @@ # to be re-built using the 2.11.1 release, we could not use 2.11.0. We could also not release the modules # after 2.11.1 was out, because that way the scala-library-all pom of 2.11.1 would depend on the old modules. # -# (*) https://github.com/sbt/sbt/blob/0.13.8/util/cross/src/main/input_sources/CrossVersionUtil.scala#L39 +# (*) https://github.com/sbt/sbt/blob/v0.13.13/util/cross/src/main/input_sources/CrossVersionUtil.scala#L41 # Binary incompatible changes in Modules: example with Scala 2.11 / 2.12 and scala-parser-combinators @@ -107,24 +108,30 @@ mkdir -p $baseDir/ivy2 rm -rf $baseDir/resolutionScratch_ mkdir -p $baseDir/resolutionScratch_ -# repo used to publish "locker" scala to (to start the bootstrap) -releaseTempRepoCred="private-repo" -releaseTempRepoUrl=${releaseTempRepoUrl-"https://scala-ci.typesafe.com/artifactory/scala-release-temp/"} -jcenterCacheUrl=${jcenterCacheUrl-"https://scala-ci.typesafe.com/artifactory/jcenter/"} - -# Used below in sbtArgs since we use a dedicated repository to share artifcacts between jobs, -# so we need to configure SBT to use these rather than its default, Maven Central. -# See http://www.scala-sbt.org/0.13/docs/Proxy-Repositories.html -sbtRepositoryConfig="$scriptsDir/repositories-scala-release" -cat > "$sbtRepositoryConfig" << EOF +function generateRepositoriesConfig(){ + # Used below in sbtArgs since we use a dedicated repository to share artifcacts between jobs, + # so we need to configure SBT to use these rather than its default, Maven Central. + # See http://www.scala-sbt.org/0.13/docs/Proxy-Repositories.html + sbtRepositoryConfig="$scriptsDir/repositories-scala-release" + jcenterCacheUrl=${jcenterCacheUrl-"https://scala-ci.typesafe.com/artifactory/jcenter/"} + cat > "$sbtRepositoryConfig" << EOF [repositories] - private-repo: $releaseTempRepoUrl + script-repo: $1 jcenter-cache: $jcenterCacheUrl typesafe-ivy-releases: https://dl.bintray.com/typesafe/ivy-releases/, [organisation]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext], bootOnly sbt-plugin-releases: https://dl.bintray.com/sbt/sbt-plugin-releases/, [organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext] maven-central local EOF +} + +integrationRepoCred="private-repo" + +# repo for locker, quick and the modules +integrationRepoUrl=${integrationRepoUrl-"https://scala-ci.typesafe.com/artifactory/scala-integration/"} + +# adding `integrationRepoUrl` to find the locker scala version when building modules +generateRepositoriesConfig $integrationRepoUrl ##### git gfxd() { @@ -198,15 +205,15 @@ sbtResolve() { # then set the version to the right one and publish (which won't re-gen the docs). # Also tried publish-local without docs using 'set publishArtifact in (Compile, packageDoc) := false' and republishing, no dice. -# Each buildModule() function is invoked twice: first to build against locker and publish to private-repo, then +# Each buildModule() function is invoked twice: first to build against locker and publish to artifactory, then # to build against the release and publish to sonatype (or publish-local if publishToSonatype is not "yes"). -# In the second round, sbtResolve is always true: the module will be found in the private-repo! +# In the second round, sbtResolve is always true: the module will be found in the artifactory! # Therefore, if MODULE_BUILT is "yes" (in the second round), we know that we need to build (and publish) the # module again. # -# Note: we tried an alternative solution in which sbtResolve would not look at private-repo, but that fails. For example, +# Note: we tried an alternative solution in which sbtResolve would not look at artifactory, but that fails. For example, # scala-xml depends on scala-library, so sbt tries to find the scala-library of the version that we are currently building, -# which exists only in private-repo. +# which exists only in artifactory. buildXML() { if [ "$XML_BUILT" != "yes" ] && [ "$forceRebuild" != "yes" ] && ( sbtResolve "org.scala-lang.modules" "scala-xml" $XML_VER ) @@ -281,7 +288,7 @@ buildActorsMigration(){ fi } -# should only be called with publishTasks publishing to private-repo +# should only be called with publishTasks publishing to artifactory buildScalacheck(){ if [ "$SCALACHECK_BUILT" != "yes" ] && [ "$forceRebuild" != "yes" ] && ( sbtResolve "org.scalacheck" "scalacheck" $SCALACHECK_VER ) then echo "Found scalacheck $SCALACHECK_VER; not building." @@ -292,9 +299,9 @@ buildScalacheck(){ fi } -# build modules, using ${buildTasks[@]} (except for Scalacheck, which is hard-coded to publish to private-repo) +# build modules, using ${buildTasks[@]} (except for Scalacheck, which is hard-coded to publish to artifactory) buildModules() { - publishTasks=('set credentials += Credentials(Path.userHome / ".credentials-private-repo")' "set every publishTo := Some(\"private-repo\" at \"$releaseTempRepoUrl\")") + publishTasks=('set credentials += Credentials(Path.userHome / ".credentials-private-repo")' "set every publishTo := Some(\"publish-repo\" at \"$integrationRepoUrl\")") buildTasks=($publishPrivateTask) buildXML buildParsers @@ -329,20 +336,19 @@ scalaVerToBinary() { local patch="$(echo $2 | sed -e "s#$RE#\3#")" # The binary version is majMin (e.g. "2.12") if - # - there's no suffix : 2.12.0, 2.12.1 - # - the suffix starts with "-bin": 2.12.0-bin-M1 - # - the patch version is > 0 : 2.12.1-M1, 1.12.3-RC2, 2.12.1-sha-nightly, 2.12.2-SNAPSHOT + # - there's no suffix : 2.12.0, 2.12.1 + # - the suffix starts with "-bin" : 2.12.1-bin-sha, 2.12.1-bin-sha-custom, 2.12.1-bin-SNAPSHOT + # - the suffix is \w+ and patch version is > 0: 2.12.1-M1, 2.12.1-RC2 (also 2.12.1-sha, 2.12.1-SNAPSHOT, which we don't use) # - # Otherwise, the binary version is the full version: 2.12.0-M1, 2.12.0-RC2, 2.12.0-sha-nightly, 2.12.0-SNAPSHOT + # Otherwise, the binary version is the full version: 2.12.0-M1, 2.12.0-RC2, 2.12.0-pre-sha, 2.12.0-pre-SNAPSHOT + # (also 2.12.0-sha, 2.12.0-SNAPSHOT, which we don't use) # - # Adapted from sbt: https://github.com/sbt/sbt/blob/0.13.8/util/cross/src/main/input_sources/CrossVersionUtil.scala#L39 + # Adapted from sbt: https://github.com/sbt/sbt/blob/v0.13.13/util/cross/src/main/input_sources/CrossVersionUtil.scala#L42 # - # Note: during the pre-release cycle of a major release (e.g. before 2.12.0), the SCALA_BINARY_VER of nightly / SNAPSHOT - # versions is the full version, e.g. 2.12.0-sha-nightly, so modules are always re-built. This is in line with what sbt - # does: for example, with scalaVersion := "2.12.0-SNAPSHOT", sbt will resolve scala-xml as scala-xml_2.12.0-SNAPSHOT. - # Once the 2.12.0 release is out, the binary version is 2.12 for all versions (e.g. for 2.12.1-sha-nightly). + # During the pre-release cycle of a major release (e.g. before 2.12.0), the SCALA_BINARY_VER of integration / SNAPSHOT + # versions is the full version, e.g. 2.12.0-pre-sha, so modules are always re-built. - if [[ "$3" == "" || "${3:0:4}" == "-bin" || "$patch" != "0" ]]; then + if [[ "$3" == "" || "${3:0:4}" == "-bin" || ("$patch" != "0" && "$3" =~ ^-[a-zA-Z0-9_]+$) ]]; then echo "$majMin" else echo "$1" @@ -363,10 +369,15 @@ determineScalaVersion() { if [ -z "$scalaTag" ] then - echo "No tag found, building nightly snapshot." + echo "No tag found, running an integration build." parseScalaProperties "build.number" SCALA_VER_BASE="$version_major.$version_minor.$version_patch" - SCALA_VER_SUFFIX="-$(git rev-parse --short HEAD)-nightly" + local shaSuffix=$(git rev-parse HEAD | cut -c1-7) + local cross="bin" + if [[ $SCALA_VER_BASE =~ ^.*\.0$ ]]; then + cross="pre" + fi + SCALA_VER_SUFFIX="-$cross-$shaSuffix" SCALADOC_SOURCE_LINKS_VER=$(git rev-parse HEAD) # TODO: publish nightly snapshot using this script - currently it's a separate jenkins job still running at EPFL. @@ -468,20 +479,31 @@ createNetrcFile() { grep 'password=' $1 | sed 's/password=\(.*\)/password \1/' >> $netrcFile } +# deletes existing artifacts (core and modules) matching the $SCALA_VER from the repository passed as argument removeExistingBuilds() { - createNetrcFile "$HOME/.credentials-private-repo" - local netrcFile="$HOME/.credentials-private-repo-netrc" - - local storageApiUrl=`echo $releaseTempRepoUrl | sed 's/\(scala-release-temp\)/api\/storage\/\1/'` - local scalaLangModules=`curl -s $storageApiUrl/org/scala-lang | jq -r '.children | .[] | "org/scala-lang" + .uri'` - - for module in "org/scalacheck" $scalaLangModules; do - local artifacts=`curl -s $storageApiUrl/$module | jq -r ".children | .[] | select(.uri | endswith(\"$SCALA_VER\")) | .uri"` - for artifact in $artifacts; do - echo "Deleting $releaseTempRepoUrl$module$artifact" - curl -s --netrc-file $netrcFile -X DELETE $releaseTempRepoUrl$module$artifact + local repoUrl=$1 + local repoPrefix="https://scala-ci.typesafe.com/artifactory/" + if [[ $repoUrl == "$repoPrefix"* ]]; then + local repoId=${1#$repoPrefix} + local storageApiUrl="${repoPrefix}api/storage/$repoId" + + createNetrcFile "$HOME/.credentials-private-repo" + local netrcFile="$HOME/.credentials-private-repo-netrc" + + # "module" is not a scala module (like scala-xml), but an artifact of a boostrap build. the variable + # contains: "org/scala-lang/modules", "org/scala-lang/scala-compiler", "org/scala-lang/scala-library", ... + local scalaLangModules=`curl -s $storageApiUrl/org/scala-lang | jq -r '.children | .[] | "org/scala-lang" + .uri' | grep -v actors-migration` + + for module in $scalaLangModules; do + local artifacts=`curl -s $storageApiUrl/$module | jq -r ".children | .[] | select(.uri | endswith(\"$SCALA_VER\")) | .uri"` + for artifact in $artifacts; do + echo "Deleting $repoUrl$module$artifact" + curl -s --netrc-file $netrcFile -X DELETE $repoUrl$module$artifact + done done - done + else + echo "Unknown repo, not deleting anything: $repoUrl" + fi } constructUpdatedModuleVersions() { @@ -507,7 +529,7 @@ constructUpdatedModuleVersions() { if [ ! -z "$SCALA_BINARY_VER" ]; then updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dscala.binary.version=$SCALA_BINARY_VER"); fi } -# build locker (scala + modules) and quick, publishing everything to private-repo +# build locker (scala + modules) and quick, publishing everything to artifactory bootstrap() { echo "### Bootstrapping" @@ -524,8 +546,8 @@ bootstrap() { # in sabbus lingo, the resulting Scala build will be used as starr to build the released Scala compiler ant -Dmaven.version.number=$SCALA_VER\ -Dremote.snapshot.repository=NOPE\ - -Dremote.release.repository=$releaseTempRepoUrl\ - -Drepository.credentials.id=$releaseTempRepoCred\ + -Dremote.release.repository=$integrationRepoUrl\ + -Drepository.credentials.id=$integrationRepoCred\ -Dscalac.args.optimise=-optimise\ -Ddocs.skip=1\ -Dlocker.skip=1\ @@ -561,14 +583,14 @@ bootstrap() { # which is fully cross-versioned (for $SCALA_VER, the version we're releasing) ant -Dstarr.version=$SCALA_VER\ -Dscala.full.version=$SCALA_VER\ - -Dextra.repo.url=$releaseTempRepoUrl\ + -Dextra.repo.url=$integrationRepoUrl\ -Dmaven.version.suffix=$SCALA_VER_SUFFIX\ ${updatedModuleVersions[@]} \ -Dupdate.versions=1\ -Dscaladoc.git.commit=$SCALADOC_SOURCE_LINKS_VER\ -Dremote.snapshot.repository=NOPE\ - -Dremote.release.repository=$releaseTempRepoUrl\ - -Drepository.credentials.id=$releaseTempRepoCred\ + -Dremote.release.repository=$integrationRepoUrl\ + -Drepository.credentials.id=$integrationRepoCred\ -Dscalac.args.optimise=-optimise\ $antBuildTask $publishPrivateTask @@ -614,7 +636,7 @@ determineScalaVersion deriveModuleVersions -removeExistingBuilds +removeExistingBuilds $integrationRepoUrl bootstrap diff --git a/src/compiler/scala/tools/nsc/settings/ScalaVersion.scala b/src/compiler/scala/tools/nsc/settings/ScalaVersion.scala index 43bdad5882..d7901730a4 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaVersion.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaVersion.scala @@ -135,7 +135,7 @@ abstract class ScalaBuild extends Ordered[ScalaBuild] { def unparse: String } /** - * A development, test, nightly, snapshot or other "unofficial" build + * A development, test, integration, snapshot or other "unofficial" build */ case class Development(id: String) extends ScalaBuild { def unparse = s"-${id}" -- cgit v1.2.3 From c8559c289de2a95a1821c8272842a1ea4e812064 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Thu, 16 Mar 2017 15:08:12 +0100 Subject: update stale comment --- scripts/jobs/integrate/bootstrap | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/jobs/integrate/bootstrap b/scripts/jobs/integrate/bootstrap index 216a93637b..85be794276 100644 --- a/scripts/jobs/integrate/bootstrap +++ b/scripts/jobs/integrate/bootstrap @@ -6,8 +6,7 @@ # - build minimal core (aka locker) of Scala, use the determined version number, publish to scala-integration # - build those modules where a binary compatible version doesn't exist, publish to scala-integration # - build Scala using the previously built core and bootstrap modules, publish to scala-integration, overwriting -# the existing artifacts (note: in 2.12.x we use scala-release-temp for locker, but that doesn't work in 2.11.x, -# because we can only pass in one `extra.repo` to ant, see comment in PR 5764). +# the existing artifacts # - for releases # - stage Scala on sonatype # - rebuild modules that needed a rebuild with this Scala build, and stage them on sonatype -- cgit v1.2.3 From 61a6f3edf794a498b51d05febc01feccaa7d3f67 Mon Sep 17 00:00:00 2001 From: jvican Date: Tue, 20 Dec 2016 08:30:30 +0100 Subject: Improve stub error messages (SCP-009 proposal) The following commit message is a squash of several commit messages. - This is the 1st commit message: Add position to stub error messages Stub errors happen when we've started the initialization of a symbol but key information of this symbol is missing (the information cannot be found in any entry of the classpath not sources). When this error happens, we better have a good error message with a position to the place where the stub error came from. This commit goes into this direction by adding a `pos` value to `StubSymbol` and filling it in in all the use sites (especifically `UnPickler`). This commit also changes some tests that test stub errors-related issues. Concretely, `t6440` is using special Partest infrastructure and doens't pretty print the position, while `t5148` which uses the conventional infrastructure does. Hence the difference in the changes for both tests. - This is the commit message #2: Add partest infrastructure to test stub errors `StubErrorMessageTest` is the friend I introduce in this commit to help state stub errors. The strategy to test them is easy and builds upon previous concepts: we reuse `StoreReporterDirectTest` and add some methods that will compile the code and simulate a missing classpath entry by removing the class files from the class directory (the folder where Scalac compiles to). This first iteration allow us to programmatically check that stub errors are emitted under certain conditions. - This is the commit message #3: Improve contents of stub error message This commit does three things: * Keep track of completing symbol while unpickling First, it removes the previous `symbolOnCompletion` definition to be more restrictive/clear and use only positions, since only positions are used to report the error (the rest of the information comes from the context of the `UnPickler`). Second, it adds a new variable called `lazyCompletingSymbol` that is responsible for keeping a reference to the symbol that produces the stub error. This symbol will usually (always?) come from the classpath entries and therefore we don't have its position (that's why we keep track of `symbolOnCompletion` as well). This is the one that we have to explicitly use in the stub error message, the culprit so to speak. Aside from these two changes, this commit modifies the existing tests that are affected by the change in the error message, which is more precise now, and adds new tests for stub errors that happen in complex inner cases and in return type of `MethodType`. * Check that order of initialization is correct With the changes introduced previously to keep track of position of symbols coming from source files, we may ask ourselves: is this going to work always? What happens if two symbols the initialization of two symbols is intermingled and the stub error message gets the wrong position? This commit adds a test case and modifications to the test infrastructure to double check empirically that this does not happen. Usually, this interaction in symbol initialization won't happen because the `UnPickler` will lazily load all the buckets necessary for a symbol to be truly initialized, with the pertinent addresses from which this information has to be deserialized. This ensures that this operation is atomic and no other symbol initialization can happen in the meantime. Even though the previous paragraph is the feeling I got from reading the sources, this commit creates a test to double-check it. My attempt to be better safe than sorry. * Improve contents of the stub error message This commit modifies the format of the previous stub error message by being more precise in its formulation. It follows the structured format: ``` s"""|Symbol '${name.nameKind} ${owner.fullName}.$name' is missing from the classpath. |This symbol is required by '${lazyCompletingSymbol.kindString} ${lazyCompletingSymbol.fullName}'. ``` This format has the advantage that is more readable and explicit on what's happening. First, we report what is missing. Then, why it was required. Hopefully, people working on direct dependencies will find the new message friendlier. Having a good test suite to check the previously added code is important. This commit checks that stub errors happen in presence of well-known and widely used Scala features. These include: * Higher kinded types. * Type definitions. * Inheritance and subclasses. * Typeclasses and implicits. - This is the commit message #4: Use `lastTreeToTyper` to get better positions The previous strategy to get the last user-defined position for knowing what was the root cause (the trigger) of stub errors relied on instrumenting `def info`. This instrumentation, while easy to implement, is inefficient since we register the positions for symbols that are already completed. However, we cannot do it only for uncompleted symbols (!hasCompleteInfo) because the positions won't be correct anymore -- definitions using stub symbols (val b = new B) are for the compiler completed, but their use throws stub errors. This means that if we initialize symbols between a definition and its use, we'll use their positions instead of the position of `b`. To work around this we use `lastTreeToTyper`. We assume that stub errors will be thrown by Typer at soonest. The benefit of this approach is better error messages. The positions used in them are now as concrete as possible since they point to the exact tree that **uses** a symbol, instead of the one that **defines** it. Have a look at `StubErrorComplexInnerClass` for an example. This commit removes the previous infrastructure and replaces it by the new one. It also removes the fields positions from the subclasses of `StubSymbol`s. - This is the commit message #5: Keep track of completing symbols Make sure that cycles don't happen by keeping track of all the symbols that are being completed by `completeInternal`. Stub errors only need the last completing symbols, but the whole stack of symbols may be useful to reporting other error like cyclic initialization issues. I've added this per Jason's suggestion. I've implemented with a list because `remove` in an array buffer is linear. Array was not an option because I would need to resize it myself. I think that even though list is not as efficient memory-wise, it probably doesn't matter since the stack will usually be small. - This is the commit message #6: Remove `isPackage` from `newStubSymbol` Remove `isPackage` since in 2.12.x its value is not used. --- src/compiler/scala/tools/nsc/Global.scala | 14 +++++++ .../nsc/symtab/classfile/ClassfileParser.scala | 13 ++++-- .../scala/tools/partest/StubErrorMessageTest.scala | 47 ++++++++++++++++++++++ src/reflect/scala/reflect/internal/Symbols.scala | 19 +++++++-- .../reflect/internal/pickling/UnPickler.scala | 22 +++++++--- test/files/neg/t5148.check | 18 ++++----- test/files/run/StubErrorBInheritsFromA.check | 6 +++ test/files/run/StubErrorBInheritsFromA.scala | 22 ++++++++++ test/files/run/StubErrorComplexInnerClass.check | 6 +++ test/files/run/StubErrorComplexInnerClass.scala | 42 +++++++++++++++++++ test/files/run/StubErrorHK.check | 6 +++ test/files/run/StubErrorHK.scala | 22 ++++++++++ test/files/run/StubErrorReturnTypeFunction.check | 6 +++ test/files/run/StubErrorReturnTypeFunction.scala | 37 +++++++++++++++++ test/files/run/StubErrorReturnTypeFunction2.check | 6 +++ test/files/run/StubErrorReturnTypeFunction2.scala | 37 +++++++++++++++++ .../run/StubErrorReturnTypePolyFunction.check | 15 +++++++ .../run/StubErrorReturnTypePolyFunction.scala | 37 +++++++++++++++++ test/files/run/StubErrorSubclasses.check | 6 +++ test/files/run/StubErrorSubclasses.scala | 21 ++++++++++ test/files/run/StubErrorTypeDef.check | 16 ++++++++ test/files/run/StubErrorTypeDef.scala | 26 ++++++++++++ test/files/run/StubErrorTypeclass.check | 6 +++ test/files/run/StubErrorTypeclass.scala | 21 ++++++++++ test/files/run/t6440b.check | 11 ++--- test/files/run/t6440b.scala | 6 ++- ...tags_without_scala_reflect_typetag_lookup.scala | 2 +- ...ut_scala_reflect_typetag_manifest_interop.scala | 2 +- 28 files changed, 461 insertions(+), 31 deletions(-) create mode 100644 src/partest-extras/scala/tools/partest/StubErrorMessageTest.scala create mode 100644 test/files/run/StubErrorBInheritsFromA.check create mode 100644 test/files/run/StubErrorBInheritsFromA.scala create mode 100644 test/files/run/StubErrorComplexInnerClass.check create mode 100644 test/files/run/StubErrorComplexInnerClass.scala create mode 100644 test/files/run/StubErrorHK.check create mode 100644 test/files/run/StubErrorHK.scala create mode 100644 test/files/run/StubErrorReturnTypeFunction.check create mode 100644 test/files/run/StubErrorReturnTypeFunction.scala create mode 100644 test/files/run/StubErrorReturnTypeFunction2.check create mode 100644 test/files/run/StubErrorReturnTypeFunction2.scala create mode 100644 test/files/run/StubErrorReturnTypePolyFunction.check create mode 100644 test/files/run/StubErrorReturnTypePolyFunction.scala create mode 100644 test/files/run/StubErrorSubclasses.check create mode 100644 test/files/run/StubErrorSubclasses.scala create mode 100644 test/files/run/StubErrorTypeDef.check create mode 100644 test/files/run/StubErrorTypeDef.scala create mode 100644 test/files/run/StubErrorTypeclass.check create mode 100644 test/files/run/StubErrorTypeclass.scala diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 8d72fd76bd..a54b92cef8 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -96,6 +96,20 @@ class Global(var currentSettings: Settings, var reporter: Reporter) def erasurePhase: Phase = if (currentRun.isDefined) currentRun.erasurePhase else NoPhase + /* Override `newStubSymbol` defined in `SymbolTable` to provide us access + * to the last tree to typer, whose position is the trigger of stub errors. */ + override def newStubSymbol(owner: Symbol, + name: Name, + missingMessage: String, + isPackage: Boolean = false): Symbol = { + val stubSymbol = super.newStubSymbol(owner, name, missingMessage, isPackage) + val stubErrorPosition = { + val lastTreeToTyper = analyzer.lastTreeToTyper + if (lastTreeToTyper != EmptyTree) lastTreeToTyper.pos else stubSymbol.pos + } + stubSymbol.setPos(stubErrorPosition) + } + // platform specific elements protected class GlobalPlatform extends { diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 9b73f203e0..e51877225f 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -1030,8 +1030,11 @@ abstract class ClassfileParser { val sflags = jflags.toScalaFlags val owner = ownerForFlags(jflags) val scope = getScope(jflags) - def newStub(name: Name) = - owner.newStubSymbol(name, s"Class file for ${entry.externalName} not found").setFlag(JAVA) + def newStub(name: Name) = { + val stub = owner.newStubSymbol(name, s"Class file for ${entry.externalName} not found") + stub.setPos(owner.pos) + stub.setFlag(JAVA) + } val (innerClass, innerModule) = if (file == NoAbstractFile) { (newStub(name.toTypeName), newStub(name.toTermName)) @@ -1152,7 +1155,11 @@ abstract class ClassfileParser { if (enclosing == clazz) entry.scope lookup name else lookupMemberAtTyperPhaseIfPossible(enclosing, name) ) - def newStub = enclosing.newStubSymbol(name, s"Unable to locate class corresponding to inner class entry for $name in owner ${entry.outerName}") + def newStub = { + enclosing + .newStubSymbol(name, s"Unable to locate class corresponding to inner class entry for $name in owner ${entry.outerName}") + .setPos(enclosing.pos) + } member.orElse(newStub) } } diff --git a/src/partest-extras/scala/tools/partest/StubErrorMessageTest.scala b/src/partest-extras/scala/tools/partest/StubErrorMessageTest.scala new file mode 100644 index 0000000000..f713b79e75 --- /dev/null +++ b/src/partest-extras/scala/tools/partest/StubErrorMessageTest.scala @@ -0,0 +1,47 @@ +package scala.tools.partest + +trait StubErrorMessageTest extends StoreReporterDirectTest { + // Stub to feed to partest, unused + def code = throw new Error("Use `userCode` instead of `code`.") + + val classpath = List(sys.props("partest.lib"), testOutput.path) + .mkString(sys.props("path.separator")) + + def compileCode(codes: String*) = { + val global = newCompiler("-cp", classpath, "-d", testOutput.path) + val sourceFiles = newSources(codes: _*) + withRun(global)(_ compileSources sourceFiles) + } + + def removeClasses(inPackage: String, classNames: Seq[String]): Unit = { + val pkg = new File(testOutput.path, inPackage) + classNames.foreach { className => + val classFile = new File(pkg, s"$className.class") + assert(classFile.exists) + assert(classFile.delete()) + } + } + + def removeFromClasspath(): Unit + def codeA: String + def codeB: String + def userCode: String + def extraUserCode: String = "" + + def show(): Unit = { + compileCode(codeA) + assert(filteredInfos.isEmpty, filteredInfos) + + compileCode(codeB) + assert(filteredInfos.isEmpty, filteredInfos) + removeFromClasspath() + + if (extraUserCode == "") compileCode(userCode) + else compileCode(userCode, extraUserCode) + import scala.reflect.internal.util.Position + filteredInfos.map { report => + print(if (report.severity == storeReporter.ERROR) "error: " else "") + println(Position.formatMessage(report.pos, report.msg, true)) + } + } +} diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 6116952c70..16b2a23c23 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -182,6 +182,17 @@ trait Symbols extends api.Symbols { self: SymbolTable => private[reflect] case class SymbolKind(accurate: String, sanitized: String, abbreviation: String) + protected def newStubSymbol(owner: Symbol, + name: Name, + missingMessage: String, + isPackage: Boolean = false): Symbol = { + name match { + case n: TypeName => if (isPackage) new StubPackageClassSymbol(owner, n, missingMessage) + else new StubClassSymbol(owner, n, missingMessage) + case _ => new StubTermSymbol(owner, name.toTermName, missingMessage) + } + } + /** The class for all symbols */ abstract class Symbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: Name) extends SymbolContextApiImpl @@ -505,9 +516,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => * failure to the point when that name is used for something, which is * often to the point of never. */ - def newStubSymbol(name: Name, missingMessage: String, isPackage: Boolean = false): Symbol = name match { - case n: TypeName => if (isPackage) new StubPackageClassSymbol(this, n, missingMessage) else new StubClassSymbol(this, n, missingMessage) - case _ => new StubTermSymbol(this, name.toTermName, missingMessage) + def newStubSymbol(name: Name, missingMessage: String, isPackage: Boolean = false): Symbol = { + // Invoke the overriden `newStubSymbol` in Global that gives us access to typer + Symbols.this.newStubSymbol(this, name, missingMessage, isPackage) } /** Given a field, construct a term symbol that represents the source construct that gave rise the field */ @@ -3491,7 +3502,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => private def fail[T](alt: T): T = { // Avoid issuing lots of redundant errors if (!hasFlag(IS_ERROR)) { - globalError(missingMessage) + globalError(pos, missingMessage) if (settings.debug.value) (new Throwable).printStackTrace diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala index a9020a3d4c..6a12d44a05 100644 --- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala @@ -266,13 +266,15 @@ abstract class UnPickler { adjust(mirrorThatLoaded(owner).missingHook(owner, name)) orElse { // (5) Create a stub symbol to defer hard failure a little longer. val advice = moduleAdvice(s"${owner.fullName}.$name") + val lazyCompletingSymbol = completingStack.headOption.getOrElse(NoSymbol) val missingMessage = - s"""|missing or invalid dependency detected while loading class file '$filename'. - |Could not access ${name.longString} in ${owner.kindString} ${owner.fullName}, - |because it (or its dependencies) are missing. Check your build definition for - |missing or conflicting dependencies. (Re-run with `-Ylog-classpath` to see the problematic classpath.) + s"""|Symbol '${name.nameKind} ${owner.fullName}.$name' is missing from the classpath. + |This symbol is required by '${lazyCompletingSymbol.kindString} ${lazyCompletingSymbol.fullName}'. + |Make sure that ${name.longString} is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. |A full rebuild may help if '$filename' was compiled against an incompatible version of ${owner.fullName}.$advice""".stripMargin - owner.newStubSymbol(name, missingMessage) + val stubName = if (tag == EXTref) name else name.toTypeName + // The position of the error message is set by `newStubSymbol` + NoSymbol.newStubSymbol(stubName, missingMessage) } } } @@ -717,11 +719,18 @@ abstract class UnPickler { new TypeError(e.msg) } + /** Keep track of the symbols pending to be initialized. + * + * Useful for reporting on stub errors and cyclic errors. + */ + private var completingStack = List.empty[Symbol] + /** A lazy type which when completed returns type at index `i`. */ private class LazyTypeRef(i: Int) extends LazyType with FlagAgnosticCompleter { private val definedAtRunId = currentRunId private val p = phase protected def completeInternal(sym: Symbol) : Unit = try { + completingStack = sym :: completingStack val tp = at(i, () => readType(sym.isTerm)) // after NMT_TRANSITION, revert `() => readType(sym.isTerm)` to `readType` // This is a temporary fix allowing to read classes generated by an older, buggy pickler. @@ -744,7 +753,10 @@ abstract class UnPickler { } catch { case e: MissingRequirementError => throw toTypeError(e) + } finally { + completingStack = completingStack.tail } + override def complete(sym: Symbol) : Unit = { completeInternal(sym) if (!isCompilerUniverse) markAllCompleted(sym) diff --git a/test/files/neg/t5148.check b/test/files/neg/t5148.check index 286ed9e04a..da0ef0fc2e 100644 --- a/test/files/neg/t5148.check +++ b/test/files/neg/t5148.check @@ -1,11 +1,7 @@ -error: missing or invalid dependency detected while loading class file 'Imports.class'. -Could not access type Wrapper in class scala.tools.nsc.interpreter.IMain.Request, -because it (or its dependencies) are missing. Check your build definition for -missing or conflicting dependencies. (Re-run with `-Ylog-classpath` to see the problematic classpath.) -A full rebuild may help if 'Imports.class' was compiled against an incompatible version of scala.tools.nsc.interpreter.IMain.Request. -error: missing or invalid dependency detected while loading class file 'Imports.class'. -Could not access type Request in class scala.tools.nsc.interpreter.IMain, -because it (or its dependencies) are missing. Check your build definition for -missing or conflicting dependencies. (Re-run with `-Ylog-classpath` to see the problematic classpath.) -A full rebuild may help if 'Imports.class' was compiled against an incompatible version of scala.tools.nsc.interpreter.IMain. -two errors found +t5148.scala:4: error: Symbol 'type .Request.Wrapper' is missing from the classpath. +This symbol is required by 'value scala.tools.nsc.interpreter.Imports.wrapper'. +Make sure that type Wrapper is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. +A full rebuild may help if 'Imports.class' was compiled against an incompatible version of .Request. +class IMain extends Imports + ^ +one error found diff --git a/test/files/run/StubErrorBInheritsFromA.check b/test/files/run/StubErrorBInheritsFromA.check new file mode 100644 index 0000000000..009f0887d4 --- /dev/null +++ b/test/files/run/StubErrorBInheritsFromA.check @@ -0,0 +1,6 @@ +error: newSource1.scala:4: Symbol 'type stuberrors.A' is missing from the classpath. +This symbol is required by 'class stuberrors.B'. +Make sure that type A is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. +A full rebuild may help if 'B.class' was compiled against an incompatible version of stuberrors. + new B + ^ diff --git a/test/files/run/StubErrorBInheritsFromA.scala b/test/files/run/StubErrorBInheritsFromA.scala new file mode 100644 index 0000000000..3e02692171 --- /dev/null +++ b/test/files/run/StubErrorBInheritsFromA.scala @@ -0,0 +1,22 @@ +object Test extends scala.tools.partest.StubErrorMessageTest { + def codeA = """ + package stuberrors + class A + """ + + def codeB = """ + package stuberrors + class B extends A + """ + + def userCode = """ + package stuberrors + class C { + new B + } + """ + + def removeFromClasspath(): Unit = { + removeClasses("stuberrors", List("A")) + } +} diff --git a/test/files/run/StubErrorComplexInnerClass.check b/test/files/run/StubErrorComplexInnerClass.check new file mode 100644 index 0000000000..fe089de8ad --- /dev/null +++ b/test/files/run/StubErrorComplexInnerClass.check @@ -0,0 +1,6 @@ +error: newSource1.scala:9: Symbol 'type stuberrors.A' is missing from the classpath. +This symbol is required by 'class stuberrors.B.BB'. +Make sure that type A is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. +A full rebuild may help if 'B.class' was compiled against an incompatible version of stuberrors. + new b.BB + ^ diff --git a/test/files/run/StubErrorComplexInnerClass.scala b/test/files/run/StubErrorComplexInnerClass.scala new file mode 100644 index 0000000000..2028644601 --- /dev/null +++ b/test/files/run/StubErrorComplexInnerClass.scala @@ -0,0 +1,42 @@ +object Test extends scala.tools.partest.StubErrorMessageTest { + def codeA = """ + package stuberrors + class A + """ + + def codeB = """ + package stuberrors + class B { + def foo: String = ??? + + // unused and should fail, but not loaded + def unsafeFoo: A = ??? + // used, B.info -> BB.info -> unpickling A -> stub error + class BB extends A + } + """ + + def userCode = """ + package stuberrors + class C { + def aloha = { + val b = new B + val d = new extra.D + d.foo + println(b.foo) + new b.BB + } + } + """ + + override def extraUserCode = """ + package extra + class D { + def foo = "Hello, World" + } + """.stripMargin + + def removeFromClasspath(): Unit = { + removeClasses("stuberrors", List("A")) + } +} diff --git a/test/files/run/StubErrorHK.check b/test/files/run/StubErrorHK.check new file mode 100644 index 0000000000..6f37f8ea41 --- /dev/null +++ b/test/files/run/StubErrorHK.check @@ -0,0 +1,6 @@ +error: newSource1.scala:4: Symbol 'type stuberrors.A' is missing from the classpath. +This symbol is required by 'type stuberrors.B.D'. +Make sure that type A is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. +A full rebuild may help if 'B.class' was compiled against an incompatible version of stuberrors. + println(new B) + ^ diff --git a/test/files/run/StubErrorHK.scala b/test/files/run/StubErrorHK.scala new file mode 100644 index 0000000000..7ee8c6d6a5 --- /dev/null +++ b/test/files/run/StubErrorHK.scala @@ -0,0 +1,22 @@ +object Test extends scala.tools.partest.StubErrorMessageTest { + def codeA = """ + package stuberrors + class A + """ + + def codeB = """ + package stuberrors + class B[D <: A] + """ + + def userCode = """ + package stuberrors + object C extends App { + println(new B) + } + """ + + def removeFromClasspath(): Unit = { + removeClasses("stuberrors", List("A")) + } +} diff --git a/test/files/run/StubErrorReturnTypeFunction.check b/test/files/run/StubErrorReturnTypeFunction.check new file mode 100644 index 0000000000..bd61d5f5fa --- /dev/null +++ b/test/files/run/StubErrorReturnTypeFunction.check @@ -0,0 +1,6 @@ +error: newSource1.scala:13: Symbol 'type stuberrors.A' is missing from the classpath. +This symbol is required by 'method stuberrors.B.foo'. +Make sure that type A is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. +A full rebuild may help if 'B.class' was compiled against an incompatible version of stuberrors. + b.foo + ^ diff --git a/test/files/run/StubErrorReturnTypeFunction.scala b/test/files/run/StubErrorReturnTypeFunction.scala new file mode 100644 index 0000000000..75a02cff63 --- /dev/null +++ b/test/files/run/StubErrorReturnTypeFunction.scala @@ -0,0 +1,37 @@ +object Test extends scala.tools.partest.StubErrorMessageTest { + def codeA = """ + package stuberrors + class A + class AA + """ + + def codeB = """ + package stuberrors + + abstract class B { + def bar: String = ??? + def foo: A = new A + def baz: String = ??? + } + """ + + def userCode = """ + package stuberrors + + abstract class C extends App { + val b = new B {} + + // Use other symbols in the meanwhile + val aa = new AA + val dummy = 1 + println(dummy) + + // Should blow up + b.foo + } + """ + + def removeFromClasspath(): Unit = { + removeClasses("stuberrors", List("A")) + } +} diff --git a/test/files/run/StubErrorReturnTypeFunction2.check b/test/files/run/StubErrorReturnTypeFunction2.check new file mode 100644 index 0000000000..bd61d5f5fa --- /dev/null +++ b/test/files/run/StubErrorReturnTypeFunction2.check @@ -0,0 +1,6 @@ +error: newSource1.scala:13: Symbol 'type stuberrors.A' is missing from the classpath. +This symbol is required by 'method stuberrors.B.foo'. +Make sure that type A is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. +A full rebuild may help if 'B.class' was compiled against an incompatible version of stuberrors. + b.foo + ^ diff --git a/test/files/run/StubErrorReturnTypeFunction2.scala b/test/files/run/StubErrorReturnTypeFunction2.scala new file mode 100644 index 0000000000..efb2f4f190 --- /dev/null +++ b/test/files/run/StubErrorReturnTypeFunction2.scala @@ -0,0 +1,37 @@ +object Test extends scala.tools.partest.StubErrorMessageTest { + def codeA = """ + package stuberrors + class A + class AA + """ + + def codeB = """ + package stuberrors + + class B { + def bar: String = ??? + def foo: A = new A + def baz: String = ??? + } + """ + + def userCode = """ + package stuberrors + + abstract class C extends App { + val b = new B {} + + // Use other symbols in the meanwhile + val aa = new AA + val dummy = 1 + println(dummy) + + // Should blow up + b.foo + } + """ + + def removeFromClasspath(): Unit = { + removeClasses("stuberrors", List("A")) + } +} diff --git a/test/files/run/StubErrorReturnTypePolyFunction.check b/test/files/run/StubErrorReturnTypePolyFunction.check new file mode 100644 index 0000000000..78e309668e --- /dev/null +++ b/test/files/run/StubErrorReturnTypePolyFunction.check @@ -0,0 +1,15 @@ +error: newSource1.scala:13: Symbol 'type stuberrors.A' is missing from the classpath. +This symbol is required by 'class stuberrors.D'. +Make sure that type A is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. +A full rebuild may help if 'D.class' was compiled against an incompatible version of stuberrors. + b.foo[D] + ^ +error: newSource1.scala:13: type arguments [stuberrors.D] do not conform to method foo's type parameter bounds [T <: stuberrors.A] + b.foo[D] + ^ +error: newSource1.scala:13: Symbol 'type stuberrors.A' is missing from the classpath. +This symbol is required by 'type stuberrors.B.T'. +Make sure that type A is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. +A full rebuild may help if 'B.class' was compiled against an incompatible version of stuberrors. + b.foo[D] + ^ diff --git a/test/files/run/StubErrorReturnTypePolyFunction.scala b/test/files/run/StubErrorReturnTypePolyFunction.scala new file mode 100644 index 0000000000..8345aaade0 --- /dev/null +++ b/test/files/run/StubErrorReturnTypePolyFunction.scala @@ -0,0 +1,37 @@ +object Test extends scala.tools.partest.StubErrorMessageTest { + def codeA = """ + package stuberrors + class A + class AA + """ + + def codeB = """ + package stuberrors + + class B { + def foo[T <: A]: T = ??? + } + + class D extends A + """ + + def userCode = """ + package stuberrors + + abstract class C extends App { + val b = new B + + // Use other symbols in the meanwhile + val aa = new AA + val dummy = 1 + println(dummy) + + // Should blow up + b.foo[D] + } + """ + + def removeFromClasspath(): Unit = { + removeClasses("stuberrors", List("A")) + } +} diff --git a/test/files/run/StubErrorSubclasses.check b/test/files/run/StubErrorSubclasses.check new file mode 100644 index 0000000000..8ccd781cad --- /dev/null +++ b/test/files/run/StubErrorSubclasses.check @@ -0,0 +1,6 @@ +error: newSource1.scala:3: Symbol 'type stuberrors.A' is missing from the classpath. +This symbol is required by 'class stuberrors.B'. +Make sure that type A is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. +A full rebuild may help if 'B.class' was compiled against an incompatible version of stuberrors. + class C extends B + ^ diff --git a/test/files/run/StubErrorSubclasses.scala b/test/files/run/StubErrorSubclasses.scala new file mode 100644 index 0000000000..b19155e20e --- /dev/null +++ b/test/files/run/StubErrorSubclasses.scala @@ -0,0 +1,21 @@ +object Test extends scala.tools.partest.StubErrorMessageTest { + def codeA = """ + package stuberrors + class A + """ + + def codeB = """ + package stuberrors + class B extends A + """ + + def userCode = """ + package stuberrors + class C extends B + """ + + def removeFromClasspath(): Unit = { + removeClasses("stuberrors", List("A")) + } +} + diff --git a/test/files/run/StubErrorTypeDef.check b/test/files/run/StubErrorTypeDef.check new file mode 100644 index 0000000000..955d9b0880 --- /dev/null +++ b/test/files/run/StubErrorTypeDef.check @@ -0,0 +1,16 @@ +error: newSource1.scala:4: overriding type D in class B with bounds <: stuberrors.A; + type D has incompatible type + new B { type D = E } + ^ +error: newSource1.scala:4: Symbol 'type stuberrors.A' is missing from the classpath. +This symbol is required by 'type stuberrors.B.D'. +Make sure that type A is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. +A full rebuild may help if 'B.class' was compiled against an incompatible version of stuberrors. + new B { type D = E } + ^ +error: newSource1.scala:4: Symbol 'type stuberrors.A' is missing from the classpath. +This symbol is required by 'class stuberrors.E'. +Make sure that type A is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. +A full rebuild may help if 'E.class' was compiled against an incompatible version of stuberrors. + new B { type D = E } + ^ diff --git a/test/files/run/StubErrorTypeDef.scala b/test/files/run/StubErrorTypeDef.scala new file mode 100644 index 0000000000..967964d815 --- /dev/null +++ b/test/files/run/StubErrorTypeDef.scala @@ -0,0 +1,26 @@ +object Test extends scala.tools.partest.StubErrorMessageTest { + def codeA = """ + package stuberrors + class A + class NestedB[T] + """ + + def codeB = """ + package stuberrors + class E extends A + abstract class B { + type D <: A + } + """ + + def userCode = """ + package stuberrors + class C { + new B { type D = E } + } + """ + + def removeFromClasspath(): Unit = { + removeClasses("stuberrors", List("A")) + } +} diff --git a/test/files/run/StubErrorTypeclass.check b/test/files/run/StubErrorTypeclass.check new file mode 100644 index 0000000000..7ecee64ec9 --- /dev/null +++ b/test/files/run/StubErrorTypeclass.check @@ -0,0 +1,6 @@ +error: newSource1.scala:4: Symbol 'type stuberrors.A' is missing from the classpath. +This symbol is required by 'value stuberrors.B.evidence$1'. +Make sure that type A is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. +A full rebuild may help if 'B.class' was compiled against an incompatible version of stuberrors. + class C { println(new B(1)) } + ^ diff --git a/test/files/run/StubErrorTypeclass.scala b/test/files/run/StubErrorTypeclass.scala new file mode 100644 index 0000000000..e9a48d5430 --- /dev/null +++ b/test/files/run/StubErrorTypeclass.scala @@ -0,0 +1,21 @@ +object Test extends scala.tools.partest.StubErrorMessageTest { + def codeA = """ + package stuberrors + class A[T] + """ + + def codeB = """ + package stuberrors + class B[T: A](val t: T) + """ + + def userCode = """ + package stuberrors + // Here we want a stub error not an implicit not found error + class C { println(new B(1)) } + """ + + def removeFromClasspath(): Unit = { + removeClasses("stuberrors", List("A")) + } +} diff --git a/test/files/run/t6440b.check b/test/files/run/t6440b.check index a6100d6d1e..07ec4f2a19 100644 --- a/test/files/run/t6440b.check +++ b/test/files/run/t6440b.check @@ -1,5 +1,6 @@ -pos: NoPosition missing or invalid dependency detected while loading class file 'U.class'. -Could not access type T in package pack1, -because it (or its dependencies) are missing. Check your build definition for -missing or conflicting dependencies. (Re-run with `-Ylog-classpath` to see the problematic classpath.) -A full rebuild may help if 'U.class' was compiled against an incompatible version of pack1. ERROR +error: newSource1.scala:4: Symbol 'type pack1.T' is missing from the classpath. +This symbol is required by 'method pack1.U.t'. +Make sure that type T is in your classpath and check for conflicting dependencies with `-Ylog-classpath`. +A full rebuild may help if 'U.class' was compiled against an incompatible version of pack1. + pack2.V.u.t // we have to fail if T.class is missing + ^ diff --git a/test/files/run/t6440b.scala b/test/files/run/t6440b.scala index 7ab9529ccb..a1ad717162 100644 --- a/test/files/run/t6440b.scala +++ b/test/files/run/t6440b.scala @@ -56,6 +56,10 @@ object Test extends StoreReporterDirectTest { // bad symbolic reference error expected (but no stack trace!) compileCode(app2) - println(filteredInfos.mkString("\n")) + import scala.reflect.internal.util.Position + filteredInfos.map { report => + print(if (report.severity == storeReporter.ERROR) "error: " else "") + println(Position.formatMessage(report.pos, report.msg, true)) + } } } diff --git a/test/files/run/typetags_without_scala_reflect_typetag_lookup.scala b/test/files/run/typetags_without_scala_reflect_typetag_lookup.scala index 3d2b9f77be..dccb2af8f5 100644 --- a/test/files/run/typetags_without_scala_reflect_typetag_lookup.scala +++ b/test/files/run/typetags_without_scala_reflect_typetag_lookup.scala @@ -38,6 +38,6 @@ object Test extends StoreReporterDirectTest { compileApp(); // we should get "missing or invalid dependency detected" errors, because we're trying to use an implicit that can't be unpickled // but we don't know the number of these errors and their order, so I just ignore them all - println(filteredInfos.filterNot(_.msg.contains("missing or invalid dependency detected")).mkString("\n")) + println(filteredInfos.filterNot(_.msg.contains("is missing from the classpath")).mkString("\n")) } } diff --git a/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.scala b/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.scala index a865f4d137..c865759588 100644 --- a/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.scala +++ b/test/files/run/typetags_without_scala_reflect_typetag_manifest_interop.scala @@ -42,6 +42,6 @@ object Test extends StoreReporterDirectTest { compileApp(); // we should get "missing or invalid dependency detected" errors, because we're trying to use an implicit that can't be unpickled // but we don't know the number of these errors and their order, so I just ignore them all - println(filteredInfos.filterNot (_.msg.contains("missing or invalid dependency detected")).mkString("\n")) + println(filteredInfos.filterNot (_.msg.contains("is missing from the classpath")).mkString("\n")) } } -- cgit v1.2.3 From 9cfa239e776c2ce6bd7447fd9de8436c5fe167ab Mon Sep 17 00:00:00 2001 From: Oscar Boykin Date: Thu, 7 Jul 2016 10:19:55 -1000 Subject: Disable stub warning by default. When we create a class symbols from a classpath elements, references to other classes that are absent from the classpath are represented as references to "stub symbols". This is not a fatal error; for instance if these references are from the signature of a method that isn't called from the program being compiled, we don't need to know anything about them. A subsequent attempt to look at the type of a stub symbols will trigger a compile error. Currently, the creation of a stub symbol incurs a warning. This commit removes that warning on the basis that it isn't something users need to worry about. javac doesn't emit a comparable warning. The warning is still issued under any of `-verbose` / `-Xdev` / `-Ydebug`. --- src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala | 2 +- test/files/run/t7439.check | 2 +- test/files/run/t8442.check | 2 +- test/files/run/t9268.check | 3 +-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index e51877225f..809effe18b 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -366,7 +366,7 @@ abstract class ClassfileParser { // - better owner than `NoSymbol` // - remove eager warning val msg = s"Class $name not found - continuing with a stub." - if (!settings.isScaladoc) warning(msg) + if ((!settings.isScaladoc) && (settings.verbose || settings.developer)) warning(msg) return NoSymbol.newStubSymbol(name.toTypeName, msg) } val completer = new loaders.ClassfileLoader(file) diff --git a/test/files/run/t7439.check b/test/files/run/t7439.check index 9ea09f9c40..b95884311a 100644 --- a/test/files/run/t7439.check +++ b/test/files/run/t7439.check @@ -1,2 +1,2 @@ Recompiling after deleting t7439-run.obj/A_1.class -pos: NoPosition Class A_1 not found - continuing with a stub. WARNING + diff --git a/test/files/run/t8442.check b/test/files/run/t8442.check index ce9e8b52ff..8b13789179 100644 --- a/test/files/run/t8442.check +++ b/test/files/run/t8442.check @@ -1 +1 @@ -pos: NoPosition Class A_1 not found - continuing with a stub. WARNING + diff --git a/test/files/run/t9268.check b/test/files/run/t9268.check index 90ef940eb3..60afcbb648 100644 --- a/test/files/run/t9268.check +++ b/test/files/run/t9268.check @@ -1,5 +1,4 @@ Compiling Client1 -pos: NoPosition Class Waiter not found - continuing with a stub. WARNING + Compiling Client2 -pos: NoPosition Class Waiter not found - continuing with a stub. WARNING pos: NoPosition Unable to locate class corresponding to inner class entry for Predicate in owner Waiter ERROR -- cgit v1.2.3 From 6008e4b295ecb3697b39ee0deacb2136eeae94f4 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 28 Mar 2017 09:18:16 -0700 Subject: Bump versions on 2.11.9 release --- build.number | 2 +- build.sbt | 2 +- scripts/jobs/integrate/windows | 2 +- test/benchmarks/build.sbt | 2 +- versions.properties | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build.number b/build.number index cf9bb0664d..eb7a952b15 100644 --- a/build.number +++ b/build.number @@ -4,7 +4,7 @@ version.major=2 version.minor=11 -version.patch=9 +version.patch=10 # This is the -N part of a version (2.9.1-1). If it's 0, it's dropped from maven versions. It should not be used again. version.bnum=0 diff --git a/build.sbt b/build.sbt index c23e5bf24b..c7576bcc60 100644 --- a/build.sbt +++ b/build.sbt @@ -113,7 +113,7 @@ lazy val publishSettings : Seq[Setting[_]] = Seq( // VersionUtil.versionPropertiesImpl for details. The standard sbt `version` setting should not be set directly. It // is the same as the Maven version and derived automatically from `baseVersion` and `baseVersionSuffix`. globalVersionSettings -baseVersion in Global := "2.11.9" +baseVersion in Global := "2.11.10" baseVersionSuffix in Global := "SNAPSHOT" mimaReferenceVersion in Global := Some("2.11.0") diff --git a/scripts/jobs/integrate/windows b/scripts/jobs/integrate/windows index 2fb92ac261..83caaaa676 100755 --- a/scripts/jobs/integrate/windows +++ b/scripts/jobs/integrate/windows @@ -12,7 +12,7 @@ javac -version ant -version ant \ - -Dstarr.version=2.11.8 \ + -Dstarr.version=2.11.9 \ -Dscalac.args.optimise=-optimise \ -Dlocker.skip=1 \ test diff --git a/test/benchmarks/build.sbt b/test/benchmarks/build.sbt index 4806ecdde8..7ffa4a4346 100644 --- a/test/benchmarks/build.sbt +++ b/test/benchmarks/build.sbt @@ -1,5 +1,5 @@ scalaHome := Some(file("../../build/pack")) -scalaVersion := "2.11.8" +scalaVersion := "2.11.9" scalacOptions ++= Seq("-feature", "-Yopt:l:classpath") lazy val root = (project in file(".")). diff --git a/versions.properties b/versions.properties index 7ce84bfe7b..55420f6c3f 100644 --- a/versions.properties +++ b/versions.properties @@ -8,7 +8,7 @@ # The scala version used for bootstrapping. This has no impact on the final classfiles: # there are two stages (locker and quick), so compiler and library are always built # with themselves. Stability is ensured by building a third stage (strap). -starr.version=2.11.8-18269ea +starr.version=2.11.9 # These are the versions of the modules that go with this release. # These properties are used during PR validation and in dbuild builds. @@ -22,7 +22,7 @@ starr.version=2.11.8-18269ea scala.binary.version=2.11 # e.g. 2.11.0-RC1, 2.11.0, 2.11.1-RC1, 2.11.1 # this defines the dependency on scala-continuations-plugin in scala-dist's pom -scala.full.version=2.11.8 +scala.full.version=2.11.9 # external modules shipped with distribution, as specified by scala-library-all's pom scala-xml.version.number=1.0.5 -- cgit v1.2.3 From 8c3d3cb6422f490be68741378169ea5f3084a277 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Mon, 3 Apr 2017 12:37:48 -0700 Subject: Revert "Handle WrappedArray the same way as ArrayOps for binary compatibility" This reverts commit f24c2603d0acee5bcb6d5d80bf1e1a4645fa74f0. --- bincompat-forward.whitelist.conf | 56 +++++----------------- .../scala/collection/mutable/WrappedArray.scala | 44 ++++++++--------- 2 files changed, 33 insertions(+), 67 deletions(-) diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index a5b3d75a8e..1db1e2f408 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -769,6 +769,18 @@ filter { matchName="scala.collection.mutable.WrappedArray#ofShort.emptyImpl" problemName=DirectMissingMethodProblem }, + { + matchName="scala.collection.mutable.WrappedArray.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray.slice" + problemName=IncompatibleResultTypeProblem + }, { matchName="scala.collection.mutable.WrappedArray#ofRef.sliceImpl" problemName=DirectMissingMethodProblem @@ -881,50 +893,6 @@ filter { matchName="scala.collection.mutable.ArrayOps#ofBoolean.emptyImpl$extension" problemName=DirectMissingMethodProblem }, - { - matchName="scala.collection.mutable.WrappedArray$ofByte" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofBoolean" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofChar" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofDouble" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofShort" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofRef" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofUnit" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofInt" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArrayImpl" - problemName=MissingClassProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofLong" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofFloat" - problemName=MissingTypesProblem - }, { matchName="scala.collection.mutable.WrappedArray#ofFloat.sliceImpl" problemName=DirectMissingMethodProblem diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala index eba740bfe4..81e0e64fb2 100644 --- a/src/library/scala/collection/mutable/WrappedArray.scala +++ b/src/library/scala/collection/mutable/WrappedArray.scala @@ -72,6 +72,17 @@ extends AbstractSeq[T] else super.toArray[U] } + override def slice(from: Int, until: Int): WrappedArray[T] = { + val start = if (from < 0) 0 else from + if (until <= start || start >= repr.length) + return emptyImpl + val end = if (until > length) length else until + sliceImpl(start, end) + } + //retain existing functionallity for existing implementations outside this file + protected def emptyImpl: WrappedArray[T] = newBuilder.result() + //retain existing functionallity for existing implementations outside this file + protected def sliceImpl(from: Int, until: Int): WrappedArray[T] = super.slice(from, until) override def stringPrefix = "WrappedArray" @@ -82,20 +93,7 @@ extends AbstractSeq[T] */ override protected[this] def newBuilder: Builder[T, WrappedArray[T]] = new WrappedArrayBuilder[T](elemTag) -} - -private[mutable] abstract class WrappedArrayImpl[T] extends WrappedArray[T] { - override def slice(from: Int, until: Int): WrappedArray[T] = { - val start = if (from < 0) 0 else from - if (until <= start || start >= repr.length) - return emptyImpl - val end = if (until > length) length else until - sliceImpl(start, end) - } - - protected def emptyImpl: WrappedArray[T] - protected def sliceImpl(from: Int, until: Int): WrappedArray[T] } /** A companion object used to create instances of `WrappedArray`. @@ -145,7 +143,7 @@ object WrappedArray { private val emptyWrappedChar = new ofChar(new Array[Char](0)) private val emptyWrappedBoolean = new ofBoolean(new Array[Boolean](0)) - final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArrayImpl[T] with Serializable { + final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArray[T] with Serializable { lazy val elemTag = ClassTag[T](arrayElementClass(array.getClass)) def length: Int = array.length def apply(index: Int): T = array(index).asInstanceOf[T] @@ -154,7 +152,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofRef[T](util.Arrays.copyOfRange[T](array, from, until)) } - final class ofByte(val array: Array[Byte]) extends WrappedArrayImpl[Byte] with Serializable { + final class ofByte(val array: Array[Byte]) extends WrappedArray[Byte] with Serializable { def elemTag = ClassTag.Byte def length: Int = array.length def apply(index: Int): Byte = array(index) @@ -163,7 +161,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofByte(util.Arrays.copyOfRange(array, from, until)) } - final class ofShort(val array: Array[Short]) extends WrappedArrayImpl[Short] with Serializable { + final class ofShort(val array: Array[Short]) extends WrappedArray[Short] with Serializable { def elemTag = ClassTag.Short def length: Int = array.length def apply(index: Int): Short = array(index) @@ -172,7 +170,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofShort(util.Arrays.copyOfRange(array, from, until)) } - final class ofChar(val array: Array[Char]) extends WrappedArrayImpl[Char] with Serializable { + final class ofChar(val array: Array[Char]) extends WrappedArray[Char] with Serializable { def elemTag = ClassTag.Char def length: Int = array.length def apply(index: Int): Char = array(index) @@ -181,7 +179,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofChar(util.Arrays.copyOfRange(array, from, until)) } - final class ofInt(val array: Array[Int]) extends WrappedArrayImpl[Int] with Serializable { + final class ofInt(val array: Array[Int]) extends WrappedArray[Int] with Serializable { def elemTag = ClassTag.Int def length: Int = array.length def apply(index: Int): Int = array(index) @@ -190,7 +188,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofInt(util.Arrays.copyOfRange(array, from, until)) } - final class ofLong(val array: Array[Long]) extends WrappedArrayImpl[Long] with Serializable { + final class ofLong(val array: Array[Long]) extends WrappedArray[Long] with Serializable { def elemTag = ClassTag.Long def length: Int = array.length def apply(index: Int): Long = array(index) @@ -199,7 +197,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofLong(util.Arrays.copyOfRange(array, from, until)) } - final class ofFloat(val array: Array[Float]) extends WrappedArrayImpl[Float] with Serializable { + final class ofFloat(val array: Array[Float]) extends WrappedArray[Float] with Serializable { def elemTag = ClassTag.Float def length: Int = array.length def apply(index: Int): Float = array(index) @@ -208,7 +206,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofFloat(util.Arrays.copyOfRange(array, from, until)) } - final class ofDouble(val array: Array[Double]) extends WrappedArrayImpl[Double] with Serializable { + final class ofDouble(val array: Array[Double]) extends WrappedArray[Double] with Serializable { def elemTag = ClassTag.Double def length: Int = array.length def apply(index: Int): Double = array(index) @@ -217,7 +215,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofDouble(util.Arrays.copyOfRange(array, from, until)) } - final class ofBoolean(val array: Array[Boolean]) extends WrappedArrayImpl[Boolean] with Serializable { + final class ofBoolean(val array: Array[Boolean]) extends WrappedArray[Boolean] with Serializable { def elemTag = ClassTag.Boolean def length: Int = array.length def apply(index: Int): Boolean = array(index) @@ -226,7 +224,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofBoolean(util.Arrays.copyOfRange(array, from, until)) } - final class ofUnit(val array: Array[Unit]) extends WrappedArrayImpl[Unit] with Serializable { + final class ofUnit(val array: Array[Unit]) extends WrappedArray[Unit] with Serializable { def elemTag = ClassTag.Unit def length: Int = array.length def apply(index: Int): Unit = array(index) -- cgit v1.2.3 From fe20cce42b879cdc25bd31af2b55091794cc11be Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Mon, 3 Apr 2017 12:38:05 -0700 Subject: Revert "Optimised implementation of List.filter/filterNot" This reverts commit eb5c51383a63c5c3420e53ef021607ff5fd20296. --- bincompat-forward.whitelist.conf | 17 ---- .../immutable/FilteredTraversableInternal.scala | 104 --------------------- src/library/scala/collection/immutable/List.scala | 2 - .../scala/reflect/runtime/JavaUniverseForce.scala | 2 +- test/files/run/repl-colon-type.check | 8 +- 5 files changed, 5 insertions(+), 128 deletions(-) delete mode 100644 src/library/scala/collection/immutable/FilteredTraversableInternal.scala diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index 1db1e2f408..023e3bddac 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -924,23 +924,6 @@ filter { { matchName="scala.collection.mutable.ArrayOps#ofFloat.emptyImpl" problemName=DirectMissingMethodProblem - }, - // introduce FilteredTraversableInternal - { - matchName="scala.collection.immutable.Nil$" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.immutable.FilteredTraversableInternal" - problemName=MissingClassProblem - }, - { - matchName="scala.collection.immutable.List" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.immutable.$colon$colon" - problemName=MissingTypesProblem } ] } diff --git a/src/library/scala/collection/immutable/FilteredTraversableInternal.scala b/src/library/scala/collection/immutable/FilteredTraversableInternal.scala deleted file mode 100644 index 35585b7826..0000000000 --- a/src/library/scala/collection/immutable/FilteredTraversableInternal.scala +++ /dev/null @@ -1,104 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala -package collection -package immutable - -import scala.annotation.tailrec - -/** - * Optimised filter functions for List - * n.b. this is an internal class to help maintain compatibility and should not be used directly. - */ -private[immutable] trait FilteredTraversableInternal[+A, +Repr <: AnyRef with TraversableLike[A, Repr]] extends TraversableLike[A, Repr] { - - // Optimized for List - - override def filter(p: A => Boolean): Self = filterImpl(p, isFlipped = false) - - override def filterNot(p: A => Boolean): Self = filterImpl(p, isFlipped = true) - - private[this] def filterImpl(p: A => Boolean, isFlipped: Boolean): Self = { - - // everything seen so far so far is not included - @tailrec def noneIn(l: Repr): Repr = { - if (l.isEmpty) - Nil.asInstanceOf[Repr] - else { - val h = l.head - val t = l.tail - if (p(h) != isFlipped) - allIn(l, t) - else - noneIn(t) - } - } - - // everything from 'start' is included, if everything from this point is in we can return the origin - // start otherwise if we discover an element that is out we must create a new partial list. - @tailrec def allIn(start: Repr, remaining: Repr): Repr = { - if (remaining.isEmpty) - start - else { - val x = remaining.head - if (p(x) != isFlipped) - allIn(start, remaining.tail) - else - partialFill(start, remaining) - } - } - - // we have seen elements that should be included then one that should be excluded, start building - def partialFill(origStart: Repr, firstMiss: Repr): Repr = { - val newHead = new ::(origStart.head, Nil) - var toProcess = origStart.tail - var currentLast = newHead - - // we know that all elements are :: until at least firstMiss.tail - while (!(toProcess eq firstMiss)) { - val newElem = new ::(toProcess.head, Nil) - currentLast.tl = newElem - currentLast = newElem - toProcess = toProcess.tail - } - - // at this point newHead points to a list which is a duplicate of all the 'in' elements up to the first miss. - // currentLast is the last element in that list. - - // now we are going to try and share as much of the tail as we can, only moving elements across when we have to. - var next = firstMiss.tail - var nextToCopy = next // the next element we would need to copy to our list if we cant share. - while (!next.isEmpty) { - // generally recommended is next.isNonEmpty but this incurs an extra method call. - val head: A = next.head - if (p(head) != isFlipped) { - next = next.tail - } else { - // its not a match - do we have outstanding elements? - while (!(nextToCopy eq next)) { - val newElem = new ::(nextToCopy.head, Nil) - currentLast.tl = newElem - currentLast = newElem - nextToCopy = nextToCopy.tail - } - nextToCopy = next.tail - next = next.tail - } - } - - // we have remaining elements - they are unchanged attach them to the end - if (!nextToCopy.isEmpty) - currentLast.tl = nextToCopy.asInstanceOf[List[A]] - - newHead.asInstanceOf[Repr] - } - - noneIn(repr) - } -} \ No newline at end of file diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index e878f49c32..8e8bf953f3 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -86,7 +86,6 @@ sealed abstract class List[+A] extends AbstractSeq[A] with Product with GenericTraversableTemplate[A, List] with LinearSeqOptimized[A, List[A]] - with FilteredTraversableInternal[A, List[A]] with Serializable { override def companion: GenericCompanion[List] = List @@ -417,7 +416,6 @@ sealed abstract class List[+A] extends AbstractSeq[A] // Create a proxy for Java serialization that allows us to avoid mutation // during de-serialization. This is the Serialization Proxy Pattern. protected final def writeReplace(): AnyRef = new List.SerializationProxy(this) - } /** The empty list. diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index f72b027a2e..45dd550e3e 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -442,8 +442,8 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.DoubleTpe definitions.BooleanTpe definitions.ScalaNumericValueClasses - definitions.ScalaValueClasses definitions.ScalaValueClassesNoUnit + definitions.ScalaValueClasses uncurry.VarargsSymbolAttachment uncurry.DesugaredParameterType diff --git a/test/files/run/repl-colon-type.check b/test/files/run/repl-colon-type.check index ca8bd0648d..21fbe34d96 100644 --- a/test/files/run/repl-colon-type.check +++ b/test/files/run/repl-colon-type.check @@ -75,7 +75,7 @@ TypeRef( ) TypeRef( TypeSymbol( - sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable + sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable ) args = List( @@ -142,7 +142,7 @@ TypeRef( args = List( TypeRef( TypeSymbol( - sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable + sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable ) args = List( @@ -175,7 +175,7 @@ PolyType( args = List( TypeRef( TypeSymbol( - sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable + sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable ) args = List(TypeParamTypeRef(TypeParam(T <: AnyVal))) @@ -198,7 +198,7 @@ PolyType( params = List(TermSymbol(x: T), TermSymbol(y: List[U])) resultType = TypeRef( TypeSymbol( - sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable + sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable ) args = List(TypeParamTypeRef(TypeParam(U >: T))) -- cgit v1.2.3 From 73c9693c8aced6945b75faa5e3765b7bc6ec21e9 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Mon, 3 Apr 2017 12:38:45 -0700 Subject: Revert "Optimize slice and take in ArrayOps, WrappedArray" This reverts commit d540bf01fe4d9e5c56a68b0d3bada9d97af77e3f. --- bincompat-backward.whitelist.conf | 41 --- bincompat-forward.whitelist.conf | 296 --------------------- .../scala/collection/mutable/ArrayOps.scala | 74 +----- .../scala/collection/mutable/WrappedArray.scala | 49 ---- 4 files changed, 10 insertions(+), 450 deletions(-) diff --git a/bincompat-backward.whitelist.conf b/bincompat-backward.whitelist.conf index 7303e8d80f..0770b3cb95 100644 --- a/bincompat-backward.whitelist.conf +++ b/bincompat-backward.whitelist.conf @@ -223,47 +223,6 @@ filter { { matchName="scala.concurrent.impl.Promise.toString" problemName=MissingMethodProblem - }, - // https://github.com/scala/scala/pull/5652 - { - matchName="scala.collection.mutable.ArrayOps#ofChar.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofShort.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofUnit.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofInt.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofBoolean.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofDouble.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofRef.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofByte.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofLong.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofFloat.slice" - problemName=FinalMethodProblem } ] } diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index 023e3bddac..7f28a718bd 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -628,302 +628,6 @@ filter { { matchName="scala.reflect.api.SerializedTypeTag.serialVersionUID" problemName=MissingFieldProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofChar" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofChar.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofChar.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofShort" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofShort.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofShort.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofByte.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofByte.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofBoolean.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofBoolean.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofChar.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofChar.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofDouble.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofDouble.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofUnit" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofUnit.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofUnit.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofInt.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofInt.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofInt" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofInt.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofInt.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofRef.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofRef.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofChar.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofChar.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofUnit.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofUnit.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofBoolean" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofBoolean.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofBoolean.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofShort.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofShort.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofShort.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofShort.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray.slice" - problemName=IncompatibleResultTypeProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofRef.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofRef.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofUnit.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofUnit.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofByte.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofByte.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofDouble.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofDouble.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOpsImpl" - problemName=MissingClassProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofInt.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofInt.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofDouble" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofDouble.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofDouble.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofRef" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofRef.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofRef.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofLong.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofLong.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofByte" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofByte.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofByte.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofFloat.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofFloat.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofLong.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofLong.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofBoolean.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofBoolean.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofFloat.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofFloat.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofLong" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofLong.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofLong.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofFloat" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofFloat.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofFloat.emptyImpl" - problemName=DirectMissingMethodProblem } ] } diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala index 04bb1074ea..00491ef20e 100644 --- a/src/library/scala/collection/mutable/ArrayOps.scala +++ b/src/library/scala/collection/mutable/ArrayOps.scala @@ -10,8 +10,6 @@ package scala package collection package mutable -import java.util - import scala.compat.Platform.arraycopy import scala.reflect.ClassTag import scala.runtime.ScalaRunTime._ @@ -177,23 +175,6 @@ trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomParalleliza } -/** to provide binary compat for 2.11 and 2.12 this class contains - * functionality that should be migrated to ArrayOps in 2.13 - * - */ -private[mutable] sealed trait ArrayOpsImpl[T] extends Any with ArrayOps[T] { - override final def slice(from: Int, until: Int): Array[T] = { - val start = if (from < 0) 0 else from - if (until <= start || start >= repr.length) - return emptyImpl - val end = if (until > length) length else until - sliceImpl(start, end) - } - protected def emptyImpl: Array[T] - protected def sliceImpl(from: Int, until: Int): Array[T] - -} - /** * A companion object for `ArrayOps`. * @@ -201,24 +182,12 @@ private[mutable] sealed trait ArrayOpsImpl[T] extends Any with ArrayOps[T] { */ object ArrayOps { - private val emptyByteArray = new Array[Byte](0) - private val emptyShortArray = new Array[Short](0) - private val emptyIntArray = new Array[Int](0) - private val emptyLongArray = new Array[Long](0) - private val emptyFloatArray = new Array[Float](0) - private val emptyDoubleArray = new Array[Double](0) - private val emptyUnitArray = new Array[Unit](0) - private val emptyCharArray = new Array[Char](0) - private val emptyBooleanArray = new Array[Boolean](0) - /** A class of `ArrayOps` for arrays containing reference types. */ - final class ofRef[T <: AnyRef](override val repr: Array[T]) extends AnyVal with ArrayOpsImpl[T] with ArrayLike[T, Array[T]] { + final class ofRef[T <: AnyRef](override val repr: Array[T]) extends AnyVal with ArrayOps[T] with ArrayLike[T, Array[T]] { override protected[this] def thisCollection: WrappedArray[T] = new WrappedArray.ofRef[T](repr) override protected[this] def toCollection(repr: Array[T]): WrappedArray[T] = new WrappedArray.ofRef[T](repr) override protected[this] def newBuilder = new ArrayBuilder.ofRef[T]()(ClassTag[T](arrayElementClass(repr.getClass))) - protected override def emptyImpl:Array[T] = util.Arrays.copyOf[T](repr,0) - protected override def sliceImpl(from: Int, until: Int): Array[T] = util.Arrays.copyOfRange[T](repr, from, until) def length: Int = repr.length def apply(index: Int): T = repr(index) @@ -226,13 +195,11 @@ object ArrayOps { } /** A class of `ArrayOps` for arrays containing `byte`s. */ -final class ofByte(override val repr: Array[Byte]) extends AnyVal with ArrayOpsImpl[Byte] with ArrayLike[Byte, Array[Byte]] { +final class ofByte(override val repr: Array[Byte]) extends AnyVal with ArrayOps[Byte] with ArrayLike[Byte, Array[Byte]] { override protected[this] def thisCollection: WrappedArray[Byte] = new WrappedArray.ofByte(repr) override protected[this] def toCollection(repr: Array[Byte]): WrappedArray[Byte] = new WrappedArray.ofByte(repr) override protected[this] def newBuilder = new ArrayBuilder.ofByte - protected override def emptyImpl = emptyByteArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Byte = repr(index) @@ -240,13 +207,11 @@ final class ofByte(override val repr: Array[Byte]) extends AnyVal with ArrayOpsI } /** A class of `ArrayOps` for arrays containing `short`s. */ -final class ofShort(override val repr: Array[Short]) extends AnyVal with ArrayOpsImpl[Short] with ArrayLike[Short, Array[Short]] { +final class ofShort(override val repr: Array[Short]) extends AnyVal with ArrayOps[Short] with ArrayLike[Short, Array[Short]] { override protected[this] def thisCollection: WrappedArray[Short] = new WrappedArray.ofShort(repr) override protected[this] def toCollection(repr: Array[Short]): WrappedArray[Short] = new WrappedArray.ofShort(repr) override protected[this] def newBuilder = new ArrayBuilder.ofShort - protected override def emptyImpl = emptyShortArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Short = repr(index) @@ -254,13 +219,11 @@ final class ofShort(override val repr: Array[Short]) extends AnyVal with ArrayOp } /** A class of `ArrayOps` for arrays containing `char`s. */ -final class ofChar(override val repr: Array[Char]) extends AnyVal with ArrayOpsImpl[Char] with ArrayLike[Char, Array[Char]] { +final class ofChar(override val repr: Array[Char]) extends AnyVal with ArrayOps[Char] with ArrayLike[Char, Array[Char]] { override protected[this] def thisCollection: WrappedArray[Char] = new WrappedArray.ofChar(repr) override protected[this] def toCollection(repr: Array[Char]): WrappedArray[Char] = new WrappedArray.ofChar(repr) override protected[this] def newBuilder = new ArrayBuilder.ofChar - protected override def emptyImpl = emptyCharArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Char = repr(index) @@ -268,13 +231,11 @@ final class ofChar(override val repr: Array[Char]) extends AnyVal with ArrayOpsI } /** A class of `ArrayOps` for arrays containing `int`s. */ -final class ofInt(override val repr: Array[Int]) extends AnyVal with ArrayOpsImpl[Int] with ArrayLike[Int, Array[Int]] { +final class ofInt(override val repr: Array[Int]) extends AnyVal with ArrayOps[Int] with ArrayLike[Int, Array[Int]] { override protected[this] def thisCollection: WrappedArray[Int] = new WrappedArray.ofInt(repr) override protected[this] def toCollection(repr: Array[Int]): WrappedArray[Int] = new WrappedArray.ofInt(repr) override protected[this] def newBuilder = new ArrayBuilder.ofInt - protected override def emptyImpl = emptyIntArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Int = repr(index) @@ -282,13 +243,11 @@ final class ofInt(override val repr: Array[Int]) extends AnyVal with ArrayOpsImp } /** A class of `ArrayOps` for arrays containing `long`s. */ -final class ofLong(override val repr: Array[Long]) extends AnyVal with ArrayOpsImpl[Long] with ArrayLike[Long, Array[Long]] { +final class ofLong(override val repr: Array[Long]) extends AnyVal with ArrayOps[Long] with ArrayLike[Long, Array[Long]] { override protected[this] def thisCollection: WrappedArray[Long] = new WrappedArray.ofLong(repr) override protected[this] def toCollection(repr: Array[Long]): WrappedArray[Long] = new WrappedArray.ofLong(repr) override protected[this] def newBuilder = new ArrayBuilder.ofLong - protected override def emptyImpl = emptyLongArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Long = repr(index) @@ -296,13 +255,11 @@ final class ofLong(override val repr: Array[Long]) extends AnyVal with ArrayOpsI } /** A class of `ArrayOps` for arrays containing `float`s. */ -final class ofFloat(override val repr: Array[Float]) extends AnyVal with ArrayOpsImpl[Float] with ArrayLike[Float, Array[Float]] { +final class ofFloat(override val repr: Array[Float]) extends AnyVal with ArrayOps[Float] with ArrayLike[Float, Array[Float]] { override protected[this] def thisCollection: WrappedArray[Float] = new WrappedArray.ofFloat(repr) override protected[this] def toCollection(repr: Array[Float]): WrappedArray[Float] = new WrappedArray.ofFloat(repr) override protected[this] def newBuilder = new ArrayBuilder.ofFloat - protected override def emptyImpl = emptyFloatArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Float = repr(index) @@ -310,13 +267,11 @@ final class ofFloat(override val repr: Array[Float]) extends AnyVal with ArrayOp } /** A class of `ArrayOps` for arrays containing `double`s. */ -final class ofDouble(override val repr: Array[Double]) extends AnyVal with ArrayOpsImpl[Double] with ArrayLike[Double, Array[Double]] { +final class ofDouble(override val repr: Array[Double]) extends AnyVal with ArrayOps[Double] with ArrayLike[Double, Array[Double]] { override protected[this] def thisCollection: WrappedArray[Double] = new WrappedArray.ofDouble(repr) override protected[this] def toCollection(repr: Array[Double]): WrappedArray[Double] = new WrappedArray.ofDouble(repr) override protected[this] def newBuilder = new ArrayBuilder.ofDouble - protected override def emptyImpl = emptyDoubleArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Double = repr(index) @@ -324,13 +279,11 @@ final class ofDouble(override val repr: Array[Double]) extends AnyVal with Array } /** A class of `ArrayOps` for arrays containing `boolean`s. */ -final class ofBoolean(override val repr: Array[Boolean]) extends AnyVal with ArrayOpsImpl[Boolean] with ArrayLike[Boolean, Array[Boolean]] { +final class ofBoolean(override val repr: Array[Boolean]) extends AnyVal with ArrayOps[Boolean] with ArrayLike[Boolean, Array[Boolean]] { override protected[this] def thisCollection: WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr) override protected[this] def toCollection(repr: Array[Boolean]): WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr) override protected[this] def newBuilder = new ArrayBuilder.ofBoolean - protected override def emptyImpl = emptyBooleanArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Boolean = repr(index) @@ -338,18 +291,11 @@ final class ofBoolean(override val repr: Array[Boolean]) extends AnyVal with Arr } /** A class of `ArrayOps` for arrays of `Unit` types. */ -final class ofUnit(override val repr: Array[Unit]) extends AnyVal with ArrayOpsImpl[Unit] with ArrayLike[Unit, Array[Unit]] { +final class ofUnit(override val repr: Array[Unit]) extends AnyVal with ArrayOps[Unit] with ArrayLike[Unit, Array[Unit]] { override protected[this] def thisCollection: WrappedArray[Unit] = new WrappedArray.ofUnit(repr) override protected[this] def toCollection(repr: Array[Unit]): WrappedArray[Unit] = new WrappedArray.ofUnit(repr) override protected[this] def newBuilder = new ArrayBuilder.ofUnit - protected override def emptyImpl = emptyUnitArray - protected override def sliceImpl(from: Int, until: Int) = { - // cant use util.Arrays.copyOfRange[Unit](repr, from, until) - Unit is special and doesnt compile - val res = new Array[Unit](until-from) - System.arraycopy(repr, from, res, 0, res.size) - res - } def length: Int = repr.length def apply(index: Int): Unit = repr(index) diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala index 81e0e64fb2..8740bda835 100644 --- a/src/library/scala/collection/mutable/WrappedArray.scala +++ b/src/library/scala/collection/mutable/WrappedArray.scala @@ -72,17 +72,6 @@ extends AbstractSeq[T] else super.toArray[U] } - override def slice(from: Int, until: Int): WrappedArray[T] = { - val start = if (from < 0) 0 else from - if (until <= start || start >= repr.length) - return emptyImpl - val end = if (until > length) length else until - sliceImpl(start, end) - } - //retain existing functionallity for existing implementations outside this file - protected def emptyImpl: WrappedArray[T] = newBuilder.result() - //retain existing functionallity for existing implementations outside this file - protected def sliceImpl(from: Int, until: Int): WrappedArray[T] = super.slice(from, until) override def stringPrefix = "WrappedArray" @@ -99,7 +88,6 @@ extends AbstractSeq[T] /** A companion object used to create instances of `WrappedArray`. */ object WrappedArray { - import java.util // This is reused for all calls to empty. private val EmptyWrappedArray = new ofRef[AnyRef](new Array[AnyRef](0)) def empty[T <: AnyRef]: WrappedArray[T] = EmptyWrappedArray.asInstanceOf[WrappedArray[T]] @@ -133,23 +121,11 @@ object WrappedArray { def newBuilder[A]: Builder[A, IndexedSeq[A]] = new ArrayBuffer - private val emptyWrappedByte = new ofByte(new Array[Byte](0)) - private val emptyWrappedShort = new ofShort(new Array[Short](0)) - private val emptyWrappedInt = new ofInt(new Array[Int](0)) - private val emptyWrappedLong = new ofLong(new Array[Long](0)) - private val emptyWrappedFloat = new ofFloat(new Array[Float](0)) - private val emptyWrappedDouble = new ofDouble(new Array[Double](0)) - private val emptyWrappedUnit = new ofUnit(new Array[Unit](0)) - private val emptyWrappedChar = new ofChar(new Array[Char](0)) - private val emptyWrappedBoolean = new ofBoolean(new Array[Boolean](0)) - final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArray[T] with Serializable { lazy val elemTag = ClassTag[T](arrayElementClass(array.getClass)) def length: Int = array.length def apply(index: Int): T = array(index).asInstanceOf[T] def update(index: Int, elem: T) { array(index) = elem } - protected override def emptyImpl = new ofRef(util.Arrays.copyOf[T](array,0)) - protected override def sliceImpl(from: Int, until: Int) = new ofRef[T](util.Arrays.copyOfRange[T](array, from, until)) } final class ofByte(val array: Array[Byte]) extends WrappedArray[Byte] with Serializable { @@ -157,8 +133,6 @@ object WrappedArray { def length: Int = array.length def apply(index: Int): Byte = array(index) def update(index: Int, elem: Byte) { array(index) = elem } - protected override def emptyImpl = emptyWrappedByte - protected override def sliceImpl(from: Int, until: Int) = new ofByte(util.Arrays.copyOfRange(array, from, until)) } final class ofShort(val array: Array[Short]) extends WrappedArray[Short] with Serializable { @@ -166,8 +140,6 @@ object WrappedArray { def length: Int = array.length def apply(index: Int): Short = array(index) def update(index: Int, elem: Short) { array(index) = elem } - protected override def emptyImpl = emptyWrappedShort - protected override def sliceImpl(from: Int, until: Int) = new ofShort(util.Arrays.copyOfRange(array, from, until)) } final class ofChar(val array: Array[Char]) extends WrappedArray[Char] with Serializable { @@ -175,8 +147,6 @@ object WrappedArray { def length: Int = array.length def apply(index: Int): Char = array(index) def update(index: Int, elem: Char) { array(index) = elem } - protected override def emptyImpl = emptyWrappedChar - protected override def sliceImpl(from: Int, until: Int) = new ofChar(util.Arrays.copyOfRange(array, from, until)) } final class ofInt(val array: Array[Int]) extends WrappedArray[Int] with Serializable { @@ -184,8 +154,6 @@ object WrappedArray { def length: Int = array.length def apply(index: Int): Int = array(index) def update(index: Int, elem: Int) { array(index) = elem } - protected override def emptyImpl = emptyWrappedInt - protected override def sliceImpl(from: Int, until: Int) = new ofInt(util.Arrays.copyOfRange(array, from, until)) } final class ofLong(val array: Array[Long]) extends WrappedArray[Long] with Serializable { @@ -193,8 +161,6 @@ object WrappedArray { def length: Int = array.length def apply(index: Int): Long = array(index) def update(index: Int, elem: Long) { array(index) = elem } - protected override def emptyImpl = emptyWrappedLong - protected override def sliceImpl(from: Int, until: Int) = new ofLong(util.Arrays.copyOfRange(array, from, until)) } final class ofFloat(val array: Array[Float]) extends WrappedArray[Float] with Serializable { @@ -202,8 +168,6 @@ object WrappedArray { def length: Int = array.length def apply(index: Int): Float = array(index) def update(index: Int, elem: Float) { array(index) = elem } - protected override def emptyImpl = emptyWrappedFloat - protected override def sliceImpl(from: Int, until: Int) = new ofFloat(util.Arrays.copyOfRange(array, from, until)) } final class ofDouble(val array: Array[Double]) extends WrappedArray[Double] with Serializable { @@ -211,8 +175,6 @@ object WrappedArray { def length: Int = array.length def apply(index: Int): Double = array(index) def update(index: Int, elem: Double) { array(index) = elem } - protected override def emptyImpl = emptyWrappedDouble - protected override def sliceImpl(from: Int, until: Int) = new ofDouble(util.Arrays.copyOfRange(array, from, until)) } final class ofBoolean(val array: Array[Boolean]) extends WrappedArray[Boolean] with Serializable { @@ -220,8 +182,6 @@ object WrappedArray { def length: Int = array.length def apply(index: Int): Boolean = array(index) def update(index: Int, elem: Boolean) { array(index) = elem } - protected override def emptyImpl = emptyWrappedBoolean - protected override def sliceImpl(from: Int, until: Int) = new ofBoolean(util.Arrays.copyOfRange(array, from, until)) } final class ofUnit(val array: Array[Unit]) extends WrappedArray[Unit] with Serializable { @@ -229,14 +189,5 @@ object WrappedArray { def length: Int = array.length def apply(index: Int): Unit = array(index) def update(index: Int, elem: Unit) { array(index) = elem } - protected override def emptyImpl = emptyWrappedUnit - protected override def sliceImpl(from: Int, until: Int) = { - // cant use - // new ofUnit(util.Arrays.copyOfRange[Unit](array, from, until)) - Unit is special and doesnt compile - // cant use util.Arrays.copyOfRange[Unit](repr, from, until) - Unit is special and doesnt compile - val res = new Array[Unit](until-from) - System.arraycopy(repr, from, res, 0, until-from) - new ofUnit(res) - } } } -- cgit v1.2.3 From b722e61682807772093cc499415d58a76fc2d0ab Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 4 Apr 2017 17:30:00 -0700 Subject: `CompleterWrapper` delegates `typeParams`. Fixes the problem reported with #5730 by xuwei-k in scala/scala-dev#352. --- src/compiler/scala/tools/nsc/typechecker/Namers.scala | 3 +++ test/files/pos/userdefined_apply_poly_overload.scala | 13 +++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 test/files/pos/userdefined_apply_poly_overload.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 69b8cb12e6..b755ee3ebd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -611,6 +611,9 @@ trait Namers extends MethodSynthesis { } class CompleterWrapper(completer: TypeCompleter) extends TypeCompleter { + // override important when completer.isInstanceOf[PolyTypeCompleter]! + override val typeParams = completer.typeParams + val tree = completer.tree override def complete(sym: Symbol): Unit = { diff --git a/test/files/pos/userdefined_apply_poly_overload.scala b/test/files/pos/userdefined_apply_poly_overload.scala new file mode 100644 index 0000000000..6760c1424f --- /dev/null +++ b/test/files/pos/userdefined_apply_poly_overload.scala @@ -0,0 +1,13 @@ +object Foo { + // spurious error if: + // - this definition precedes that of apply (which is overloaded with the synthetic one derived from the case class) + // - AND `Foo.apply` is explicitly applied to `[A]` (no error if `[A]` is inferred) + // + def referToPolyOverloadedApply[A]: Foo[A] = Foo.apply[A]("bla") + // ^ + // found : String("bla") + // required: Int + + def apply[A](x: Int): Foo[A] = ??? +} +case class Foo[A](x: String) // must be polymorphic -- cgit v1.2.3 From 7fa382355493354292fe5356bb4e6c72f56f43b9 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Fri, 7 Apr 2017 07:37:47 -0700 Subject: Bye bye JIRA --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index c2891390d4..d4babc4642 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,7 @@ In order to get in touch with Scala contributors, join the # Reporting issues -We're still using Jira for issue reporting, so please [report any issues](https://issues.scala-lang.org) over there. -(We would love to start using GitHub Issues, but we're too resource-constrained to take on this migration right now.) +Please report bugs at the [scala/bug issue tracker](https://github.com/scala/bug/issues). We use the [scala/scala-dev tracker](https://github.com/scala/scala-dev/issues) for coordinating bigger work items. # Get in touch! If you need some help with your PR at any time, please feel free to @-mention anyone from the list below, and we will do our best to help you out: -- cgit v1.2.3 From a11918d1053f3b0af32d7bd7fb5b75acb31724ff Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Fri, 7 Apr 2017 16:47:56 -0700 Subject: Revert "Handle WrappedArray the same way as ArrayOps for binary compatibility" This reverts commit f24c2603d0acee5bcb6d5d80bf1e1a4645fa74f0. --- bincompat-forward.whitelist.conf | 56 +++++----------------- .../scala/collection/mutable/WrappedArray.scala | 44 ++++++++--------- 2 files changed, 33 insertions(+), 67 deletions(-) diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index 3025edee66..dc2199bcb6 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -227,6 +227,18 @@ filter { matchName="scala.collection.mutable.WrappedArray#ofShort.emptyImpl" problemName=DirectMissingMethodProblem }, + { + matchName="scala.collection.mutable.WrappedArray.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray.slice" + problemName=IncompatibleResultTypeProblem + }, { matchName="scala.collection.mutable.WrappedArray#ofRef.sliceImpl" problemName=DirectMissingMethodProblem @@ -339,50 +351,6 @@ filter { matchName="scala.collection.mutable.ArrayOps#ofBoolean.emptyImpl$extension" problemName=DirectMissingMethodProblem }, - { - matchName="scala.collection.mutable.WrappedArray$ofByte" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofBoolean" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofChar" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofDouble" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofShort" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofRef" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofUnit" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofInt" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArrayImpl" - problemName=MissingClassProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofLong" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.WrappedArray$ofFloat" - problemName=MissingTypesProblem - }, { matchName="scala.collection.mutable.WrappedArray#ofFloat.sliceImpl" problemName=DirectMissingMethodProblem diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala index d0919c4357..d5ab0f0c01 100644 --- a/src/library/scala/collection/mutable/WrappedArray.scala +++ b/src/library/scala/collection/mutable/WrappedArray.scala @@ -75,6 +75,17 @@ extends AbstractSeq[T] else super.toArray[U] } + override def slice(from: Int, until: Int): WrappedArray[T] = { + val start = if (from < 0) 0 else from + if (until <= start || start >= repr.length) + return emptyImpl + val end = if (until > length) length else until + sliceImpl(start, end) + } + //retain existing functionallity for existing implementations outside this file + protected def emptyImpl: WrappedArray[T] = newBuilder.result() + //retain existing functionallity for existing implementations outside this file + protected def sliceImpl(from: Int, until: Int): WrappedArray[T] = super.slice(from, until) override def stringPrefix = "WrappedArray" @@ -85,20 +96,7 @@ extends AbstractSeq[T] */ override protected[this] def newBuilder: Builder[T, WrappedArray[T]] = new WrappedArrayBuilder[T](elemTag) -} - -private[mutable] abstract class WrappedArrayImpl[T] extends WrappedArray[T] { - override def slice(from: Int, until: Int): WrappedArray[T] = { - val start = if (from < 0) 0 else from - if (until <= start || start >= repr.length) - return emptyImpl - val end = if (until > length) length else until - sliceImpl(start, end) - } - - protected def emptyImpl: WrappedArray[T] - protected def sliceImpl(from: Int, until: Int): WrappedArray[T] } /** A companion object used to create instances of `WrappedArray`. @@ -148,7 +146,7 @@ object WrappedArray { private val emptyWrappedChar = new ofChar(new Array[Char](0)) private val emptyWrappedBoolean = new ofBoolean(new Array[Boolean](0)) - final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArrayImpl[T] with Serializable { + final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArray[T] with Serializable { lazy val elemTag = ClassTag[T](array.getClass.getComponentType) def length: Int = array.length def apply(index: Int): T = array(index).asInstanceOf[T] @@ -162,7 +160,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofRef[T](util.Arrays.copyOfRange[T](array, from, until)) } - final class ofByte(val array: Array[Byte]) extends WrappedArrayImpl[Byte] with Serializable { + final class ofByte(val array: Array[Byte]) extends WrappedArray[Byte] with Serializable { def elemTag = ClassTag.Byte def length: Int = array.length def apply(index: Int): Byte = array(index) @@ -176,7 +174,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofByte(util.Arrays.copyOfRange(array, from, until)) } - final class ofShort(val array: Array[Short]) extends WrappedArrayImpl[Short] with Serializable { + final class ofShort(val array: Array[Short]) extends WrappedArray[Short] with Serializable { def elemTag = ClassTag.Short def length: Int = array.length def apply(index: Int): Short = array(index) @@ -190,7 +188,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofShort(util.Arrays.copyOfRange(array, from, until)) } - final class ofChar(val array: Array[Char]) extends WrappedArrayImpl[Char] with Serializable { + final class ofChar(val array: Array[Char]) extends WrappedArray[Char] with Serializable { def elemTag = ClassTag.Char def length: Int = array.length def apply(index: Int): Char = array(index) @@ -204,7 +202,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofChar(util.Arrays.copyOfRange(array, from, until)) } - final class ofInt(val array: Array[Int]) extends WrappedArrayImpl[Int] with Serializable { + final class ofInt(val array: Array[Int]) extends WrappedArray[Int] with Serializable { def elemTag = ClassTag.Int def length: Int = array.length def apply(index: Int): Int = array(index) @@ -218,7 +216,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofInt(util.Arrays.copyOfRange(array, from, until)) } - final class ofLong(val array: Array[Long]) extends WrappedArrayImpl[Long] with Serializable { + final class ofLong(val array: Array[Long]) extends WrappedArray[Long] with Serializable { def elemTag = ClassTag.Long def length: Int = array.length def apply(index: Int): Long = array(index) @@ -232,7 +230,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofLong(util.Arrays.copyOfRange(array, from, until)) } - final class ofFloat(val array: Array[Float]) extends WrappedArrayImpl[Float] with Serializable { + final class ofFloat(val array: Array[Float]) extends WrappedArray[Float] with Serializable { def elemTag = ClassTag.Float def length: Int = array.length def apply(index: Int): Float = array(index) @@ -246,7 +244,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofFloat(util.Arrays.copyOfRange(array, from, until)) } - final class ofDouble(val array: Array[Double]) extends WrappedArrayImpl[Double] with Serializable { + final class ofDouble(val array: Array[Double]) extends WrappedArray[Double] with Serializable { def elemTag = ClassTag.Double def length: Int = array.length def apply(index: Int): Double = array(index) @@ -260,7 +258,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofDouble(util.Arrays.copyOfRange(array, from, until)) } - final class ofBoolean(val array: Array[Boolean]) extends WrappedArrayImpl[Boolean] with Serializable { + final class ofBoolean(val array: Array[Boolean]) extends WrappedArray[Boolean] with Serializable { def elemTag = ClassTag.Boolean def length: Int = array.length def apply(index: Int): Boolean = array(index) @@ -274,7 +272,7 @@ object WrappedArray { protected override def sliceImpl(from: Int, until: Int) = new ofBoolean(util.Arrays.copyOfRange(array, from, until)) } - final class ofUnit(val array: Array[Unit]) extends WrappedArrayImpl[Unit] with Serializable { + final class ofUnit(val array: Array[Unit]) extends WrappedArray[Unit] with Serializable { def elemTag = ClassTag.Unit def length: Int = array.length def apply(index: Int): Unit = array(index) -- cgit v1.2.3 From 76babbb6728e5daf4fb95444273f6f8e0a4098d7 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Fri, 7 Apr 2017 16:50:27 -0700 Subject: Revert "Optimised implementation of List.filter/filterNot" This reverts commit eb5c51383a63c5c3420e53ef021607ff5fd20296. --- bincompat-forward.whitelist.conf | 17 ---- .../immutable/FilteredTraversableInternal.scala | 104 --------------------- src/library/scala/collection/immutable/List.scala | 2 - .../scala/reflect/runtime/JavaUniverseForce.scala | 2 +- test/files/run/repl-colon-type.check | 8 +- 5 files changed, 5 insertions(+), 128 deletions(-) delete mode 100644 src/library/scala/collection/immutable/FilteredTraversableInternal.scala diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index dc2199bcb6..8c5718ac7d 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -383,23 +383,6 @@ filter { matchName="scala.collection.mutable.ArrayOps#ofFloat.emptyImpl" problemName=DirectMissingMethodProblem }, - // introduce FilteredTraversableInternal - { - matchName="scala.collection.immutable.Nil$" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.immutable.FilteredTraversableInternal" - problemName=MissingClassProblem - }, - { - matchName="scala.collection.immutable.List" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.immutable.$colon$colon" - problemName=MissingTypesProblem - }, { matchName="scala.annotation.showAsInfix$" problemName=MissingClassProblem diff --git a/src/library/scala/collection/immutable/FilteredTraversableInternal.scala b/src/library/scala/collection/immutable/FilteredTraversableInternal.scala deleted file mode 100644 index 35585b7826..0000000000 --- a/src/library/scala/collection/immutable/FilteredTraversableInternal.scala +++ /dev/null @@ -1,104 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala -package collection -package immutable - -import scala.annotation.tailrec - -/** - * Optimised filter functions for List - * n.b. this is an internal class to help maintain compatibility and should not be used directly. - */ -private[immutable] trait FilteredTraversableInternal[+A, +Repr <: AnyRef with TraversableLike[A, Repr]] extends TraversableLike[A, Repr] { - - // Optimized for List - - override def filter(p: A => Boolean): Self = filterImpl(p, isFlipped = false) - - override def filterNot(p: A => Boolean): Self = filterImpl(p, isFlipped = true) - - private[this] def filterImpl(p: A => Boolean, isFlipped: Boolean): Self = { - - // everything seen so far so far is not included - @tailrec def noneIn(l: Repr): Repr = { - if (l.isEmpty) - Nil.asInstanceOf[Repr] - else { - val h = l.head - val t = l.tail - if (p(h) != isFlipped) - allIn(l, t) - else - noneIn(t) - } - } - - // everything from 'start' is included, if everything from this point is in we can return the origin - // start otherwise if we discover an element that is out we must create a new partial list. - @tailrec def allIn(start: Repr, remaining: Repr): Repr = { - if (remaining.isEmpty) - start - else { - val x = remaining.head - if (p(x) != isFlipped) - allIn(start, remaining.tail) - else - partialFill(start, remaining) - } - } - - // we have seen elements that should be included then one that should be excluded, start building - def partialFill(origStart: Repr, firstMiss: Repr): Repr = { - val newHead = new ::(origStart.head, Nil) - var toProcess = origStart.tail - var currentLast = newHead - - // we know that all elements are :: until at least firstMiss.tail - while (!(toProcess eq firstMiss)) { - val newElem = new ::(toProcess.head, Nil) - currentLast.tl = newElem - currentLast = newElem - toProcess = toProcess.tail - } - - // at this point newHead points to a list which is a duplicate of all the 'in' elements up to the first miss. - // currentLast is the last element in that list. - - // now we are going to try and share as much of the tail as we can, only moving elements across when we have to. - var next = firstMiss.tail - var nextToCopy = next // the next element we would need to copy to our list if we cant share. - while (!next.isEmpty) { - // generally recommended is next.isNonEmpty but this incurs an extra method call. - val head: A = next.head - if (p(head) != isFlipped) { - next = next.tail - } else { - // its not a match - do we have outstanding elements? - while (!(nextToCopy eq next)) { - val newElem = new ::(nextToCopy.head, Nil) - currentLast.tl = newElem - currentLast = newElem - nextToCopy = nextToCopy.tail - } - nextToCopy = next.tail - next = next.tail - } - } - - // we have remaining elements - they are unchanged attach them to the end - if (!nextToCopy.isEmpty) - currentLast.tl = nextToCopy.asInstanceOf[List[A]] - - newHead.asInstanceOf[Repr] - } - - noneIn(repr) - } -} \ No newline at end of file diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index e12ce7c2eb..550b987cb6 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -88,7 +88,6 @@ sealed abstract class List[+A] extends AbstractSeq[A] with Product with GenericTraversableTemplate[A, List] with LinearSeqOptimized[A, List[A]] - with FilteredTraversableInternal[A, List[A]] with scala.Serializable { override def companion: GenericCompanion[List] = List @@ -414,7 +413,6 @@ sealed abstract class List[+A] extends AbstractSeq[A] // Create a proxy for Java serialization that allows us to avoid mutation // during deserialization. This is the Serialization Proxy Pattern. protected final def writeReplace(): AnyRef = new List.SerializationProxy(this) - } /** The empty list. diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index 72e21f67fe..9138ed3f02 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -459,8 +459,8 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.DoubleTpe definitions.BooleanTpe definitions.ScalaNumericValueClasses - definitions.ScalaValueClasses definitions.ScalaValueClassesNoUnit + definitions.ScalaValueClasses uncurry.VarargsSymbolAttachment uncurry.DesugaredParameterType diff --git a/test/files/run/repl-colon-type.check b/test/files/run/repl-colon-type.check index 5b7a3c7506..1217e8d8c2 100644 --- a/test/files/run/repl-colon-type.check +++ b/test/files/run/repl-colon-type.check @@ -75,7 +75,7 @@ TypeRef( ) TypeRef( TypeSymbol( - sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable + sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable ) args = List( @@ -142,7 +142,7 @@ TypeRef( args = List( TypeRef( TypeSymbol( - sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable + sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable ) args = List( @@ -175,7 +175,7 @@ PolyType( args = List( TypeRef( TypeSymbol( - sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable + sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable ) args = List(TypeParamTypeRef(TypeParam(T <: AnyVal))) @@ -198,7 +198,7 @@ PolyType( params = List(TermSymbol(x: T), TermSymbol(y: List[U])) resultType = TypeRef( TypeSymbol( - sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable + sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable ) args = List(TypeParamTypeRef(TypeParam(U >: T))) -- cgit v1.2.3 From 0365d58f62e5f21a2723365cb21636f382474805 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Fri, 7 Apr 2017 17:04:40 -0700 Subject: Revert "Optimize slice and take in ArrayOps, WrappedArray" This reverts commit d540bf01fe4d9e5c56a68b0d3bada9d97af77e3f. --- bincompat-backward.whitelist.conf | 41 --- bincompat-forward.whitelist.conf | 296 --------------------- .../scala/collection/mutable/ArrayOps.scala | 76 +----- .../scala/collection/mutable/WrappedArray.scala | 49 ---- 4 files changed, 11 insertions(+), 451 deletions(-) diff --git a/bincompat-backward.whitelist.conf b/bincompat-backward.whitelist.conf index 3d4e40a00d..1d4a6d82db 100644 --- a/bincompat-backward.whitelist.conf +++ b/bincompat-backward.whitelist.conf @@ -238,47 +238,6 @@ filter { { matchName="scala.concurrent.impl.Promise.toString" problemName=MissingMethodProblem - }, - // https://github.com/scala/scala/pull/5652 - { - matchName="scala.collection.mutable.ArrayOps#ofChar.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofShort.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofUnit.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofInt.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofBoolean.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofDouble.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofRef.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofByte.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofLong.slice" - problemName=FinalMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofFloat.slice" - problemName=FinalMethodProblem } ] } diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index 8c5718ac7d..24c372386f 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -87,302 +87,6 @@ filter { matchName="scala.reflect.api.SerializedTypeTag.serialVersionUID" problemName=MissingFieldProblem }, - { - matchName="scala.collection.mutable.ArrayOps$ofChar" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofChar.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofChar.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofShort" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofShort.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofShort.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofByte.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofByte.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofBoolean.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofBoolean.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofChar.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofChar.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofDouble.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofDouble.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofUnit" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofUnit.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofUnit.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofInt.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofInt.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofInt" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofInt.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofInt.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofRef.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofRef.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofChar.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofChar.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofUnit.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofUnit.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofBoolean" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofBoolean.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofBoolean.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofShort.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofShort.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofShort.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofShort.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray.slice" - problemName=IncompatibleResultTypeProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofRef.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofRef.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofUnit.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofUnit.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofByte.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofByte.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofDouble.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofDouble.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOpsImpl" - problemName=MissingClassProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofInt.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofInt.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofDouble" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofDouble.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofDouble.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofRef" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofRef.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofRef.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofLong.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofLong.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofByte" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofByte.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofByte.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofFloat.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofFloat.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofLong.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofLong.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofBoolean.sliceImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofBoolean.emptyImpl$extension" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofFloat.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.WrappedArray#ofFloat.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofLong" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofLong.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofLong.emptyImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps$ofFloat" - problemName=MissingTypesProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofFloat.sliceImpl" - problemName=DirectMissingMethodProblem - }, - { - matchName="scala.collection.mutable.ArrayOps#ofFloat.emptyImpl" - problemName=DirectMissingMethodProblem - }, { matchName="scala.annotation.showAsInfix$" problemName=MissingClassProblem diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala index 5de3dad256..0f83fd92c1 100644 --- a/src/library/scala/collection/mutable/ArrayOps.scala +++ b/src/library/scala/collection/mutable/ArrayOps.scala @@ -10,8 +10,6 @@ package scala package collection package mutable -import java.util - import scala.reflect.ClassTag import parallel.mutable.ParArray @@ -182,23 +180,6 @@ sealed trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomPara def seq = thisCollection } -/** to provide binary compat for 2.11 and 2.12 this class contains - * functionality that should be migrated to ArrayOps in 2.13 - * - */ -private[mutable] sealed trait ArrayOpsImpl[T] extends Any with ArrayOps[T] { - override final def slice(from: Int, until: Int): Array[T] = { - val start = if (from < 0) 0 else from - if (until <= start || start >= repr.length) - return emptyImpl - val end = if (until > length) length else until - sliceImpl(start, end) - } - protected def emptyImpl: Array[T] - protected def sliceImpl(from: Int, until: Int): Array[T] - -} - /** * A companion object for `ArrayOps`. * @@ -206,24 +187,12 @@ private[mutable] sealed trait ArrayOpsImpl[T] extends Any with ArrayOps[T] { */ object ArrayOps { - private val emptyByteArray = new Array[Byte](0) - private val emptyShortArray = new Array[Short](0) - private val emptyIntArray = new Array[Int](0) - private val emptyLongArray = new Array[Long](0) - private val emptyFloatArray = new Array[Float](0) - private val emptyDoubleArray = new Array[Double](0) - private val emptyUnitArray = new Array[Unit](0) - private val emptyCharArray = new Array[Char](0) - private val emptyBooleanArray = new Array[Boolean](0) - - /** A subclass of `ArrayOps` for arrays containing reference types. */ - final class ofRef[T <: AnyRef](override val repr: Array[T]) extends AnyVal with ArrayOpsImpl[T] with ArrayLike[T, Array[T]] { + /** A class of `ArrayOps` for arrays containing reference types. */ + final class ofRef[T <: AnyRef](override val repr: Array[T]) extends AnyVal with ArrayOps[T] with ArrayLike[T, Array[T]] { override protected[this] def thisCollection: WrappedArray[T] = new WrappedArray.ofRef[T](repr) override protected[this] def toCollection(repr: Array[T]): WrappedArray[T] = new WrappedArray.ofRef[T](repr) override protected[this] def newBuilder = new ArrayBuilder.ofRef[T]()(ClassTag[T](repr.getClass.getComponentType)) - protected override def emptyImpl:Array[T] = util.Arrays.copyOf[T](repr,0) - protected override def sliceImpl(from: Int, until: Int): Array[T] = util.Arrays.copyOfRange[T](repr, from, until) def length: Int = repr.length def apply(index: Int): T = repr(index) @@ -231,13 +200,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Byte`s. */ - final class ofByte(override val repr: Array[Byte]) extends AnyVal with ArrayOpsImpl[Byte] with ArrayLike[Byte, Array[Byte]] { + final class ofByte(override val repr: Array[Byte]) extends AnyVal with ArrayOps[Byte] with ArrayLike[Byte, Array[Byte]] { override protected[this] def thisCollection: WrappedArray[Byte] = new WrappedArray.ofByte(repr) override protected[this] def toCollection(repr: Array[Byte]): WrappedArray[Byte] = new WrappedArray.ofByte(repr) override protected[this] def newBuilder = new ArrayBuilder.ofByte - protected override def emptyImpl = emptyByteArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Byte = repr(index) @@ -245,13 +212,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Short`s. */ - final class ofShort(override val repr: Array[Short]) extends AnyVal with ArrayOpsImpl[Short] with ArrayLike[Short, Array[Short]] { + final class ofShort(override val repr: Array[Short]) extends AnyVal with ArrayOps[Short] with ArrayLike[Short, Array[Short]] { override protected[this] def thisCollection: WrappedArray[Short] = new WrappedArray.ofShort(repr) override protected[this] def toCollection(repr: Array[Short]): WrappedArray[Short] = new WrappedArray.ofShort(repr) override protected[this] def newBuilder = new ArrayBuilder.ofShort - protected override def emptyImpl = emptyShortArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Short = repr(index) @@ -259,13 +224,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Char`s. */ - final class ofChar(override val repr: Array[Char]) extends AnyVal with ArrayOpsImpl[Char] with ArrayLike[Char, Array[Char]] { + final class ofChar(override val repr: Array[Char]) extends AnyVal with ArrayOps[Char] with ArrayLike[Char, Array[Char]] { override protected[this] def thisCollection: WrappedArray[Char] = new WrappedArray.ofChar(repr) override protected[this] def toCollection(repr: Array[Char]): WrappedArray[Char] = new WrappedArray.ofChar(repr) override protected[this] def newBuilder = new ArrayBuilder.ofChar - protected override def emptyImpl = emptyCharArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Char = repr(index) @@ -273,13 +236,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Int`s. */ - final class ofInt(override val repr: Array[Int]) extends AnyVal with ArrayOpsImpl[Int] with ArrayLike[Int, Array[Int]] { + final class ofInt(override val repr: Array[Int]) extends AnyVal with ArrayOps[Int] with ArrayLike[Int, Array[Int]] { override protected[this] def thisCollection: WrappedArray[Int] = new WrappedArray.ofInt(repr) override protected[this] def toCollection(repr: Array[Int]): WrappedArray[Int] = new WrappedArray.ofInt(repr) override protected[this] def newBuilder = new ArrayBuilder.ofInt - protected override def emptyImpl = emptyIntArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Int = repr(index) @@ -287,13 +248,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Long`s. */ - final class ofLong(override val repr: Array[Long]) extends AnyVal with ArrayOpsImpl[Long] with ArrayLike[Long, Array[Long]] { + final class ofLong(override val repr: Array[Long]) extends AnyVal with ArrayOps[Long] with ArrayLike[Long, Array[Long]] { override protected[this] def thisCollection: WrappedArray[Long] = new WrappedArray.ofLong(repr) override protected[this] def toCollection(repr: Array[Long]): WrappedArray[Long] = new WrappedArray.ofLong(repr) override protected[this] def newBuilder = new ArrayBuilder.ofLong - protected override def emptyImpl = emptyLongArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Long = repr(index) @@ -301,13 +260,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Float`s. */ - final class ofFloat(override val repr: Array[Float]) extends AnyVal with ArrayOpsImpl[Float] with ArrayLike[Float, Array[Float]] { + final class ofFloat(override val repr: Array[Float]) extends AnyVal with ArrayOps[Float] with ArrayLike[Float, Array[Float]] { override protected[this] def thisCollection: WrappedArray[Float] = new WrappedArray.ofFloat(repr) override protected[this] def toCollection(repr: Array[Float]): WrappedArray[Float] = new WrappedArray.ofFloat(repr) override protected[this] def newBuilder = new ArrayBuilder.ofFloat - protected override def emptyImpl = emptyFloatArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Float = repr(index) @@ -315,13 +272,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Double`s. */ - final class ofDouble(override val repr: Array[Double]) extends AnyVal with ArrayOpsImpl[Double] with ArrayLike[Double, Array[Double]] { + final class ofDouble(override val repr: Array[Double]) extends AnyVal with ArrayOps[Double] with ArrayLike[Double, Array[Double]] { override protected[this] def thisCollection: WrappedArray[Double] = new WrappedArray.ofDouble(repr) override protected[this] def toCollection(repr: Array[Double]): WrappedArray[Double] = new WrappedArray.ofDouble(repr) override protected[this] def newBuilder = new ArrayBuilder.ofDouble - protected override def emptyImpl = emptyDoubleArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Double = repr(index) @@ -329,13 +284,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Boolean`s. */ - final class ofBoolean(override val repr: Array[Boolean]) extends AnyVal with ArrayOpsImpl[Boolean] with ArrayLike[Boolean, Array[Boolean]] { + final class ofBoolean(override val repr: Array[Boolean]) extends AnyVal with ArrayOps[Boolean] with ArrayLike[Boolean, Array[Boolean]] { override protected[this] def thisCollection: WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr) override protected[this] def toCollection(repr: Array[Boolean]): WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr) override protected[this] def newBuilder = new ArrayBuilder.ofBoolean - protected override def emptyImpl = emptyBooleanArray - protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Boolean = repr(index) @@ -343,18 +296,11 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays of `Unit` types. */ - final class ofUnit(override val repr: Array[Unit]) extends AnyVal with ArrayOpsImpl[Unit] with ArrayLike[Unit, Array[Unit]] { + final class ofUnit(override val repr: Array[Unit]) extends AnyVal with ArrayOps[Unit] with ArrayLike[Unit, Array[Unit]] { override protected[this] def thisCollection: WrappedArray[Unit] = new WrappedArray.ofUnit(repr) override protected[this] def toCollection(repr: Array[Unit]): WrappedArray[Unit] = new WrappedArray.ofUnit(repr) override protected[this] def newBuilder = new ArrayBuilder.ofUnit - protected override def emptyImpl = emptyUnitArray - protected override def sliceImpl(from: Int, until: Int) = { - // cant use util.Arrays.copyOfRange[Unit](repr, from, until) - Unit is special and doesnt compile - val res = new Array[Unit](until-from) - System.arraycopy(repr, from, res, 0, res.size) - res - } def length: Int = repr.length def apply(index: Int): Unit = repr(index) diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala index d5ab0f0c01..0b5ebe7e9a 100644 --- a/src/library/scala/collection/mutable/WrappedArray.scala +++ b/src/library/scala/collection/mutable/WrappedArray.scala @@ -75,17 +75,6 @@ extends AbstractSeq[T] else super.toArray[U] } - override def slice(from: Int, until: Int): WrappedArray[T] = { - val start = if (from < 0) 0 else from - if (until <= start || start >= repr.length) - return emptyImpl - val end = if (until > length) length else until - sliceImpl(start, end) - } - //retain existing functionallity for existing implementations outside this file - protected def emptyImpl: WrappedArray[T] = newBuilder.result() - //retain existing functionallity for existing implementations outside this file - protected def sliceImpl(from: Int, until: Int): WrappedArray[T] = super.slice(from, until) override def stringPrefix = "WrappedArray" @@ -102,7 +91,6 @@ extends AbstractSeq[T] /** A companion object used to create instances of `WrappedArray`. */ object WrappedArray { - import java.util // This is reused for all calls to empty. private val EmptyWrappedArray = new ofRef[AnyRef](new Array[AnyRef](0)) def empty[T <: AnyRef]: WrappedArray[T] = EmptyWrappedArray.asInstanceOf[WrappedArray[T]] @@ -136,16 +124,6 @@ object WrappedArray { def newBuilder[A]: Builder[A, IndexedSeq[A]] = new ArrayBuffer - private val emptyWrappedByte = new ofByte(new Array[Byte](0)) - private val emptyWrappedShort = new ofShort(new Array[Short](0)) - private val emptyWrappedInt = new ofInt(new Array[Int](0)) - private val emptyWrappedLong = new ofLong(new Array[Long](0)) - private val emptyWrappedFloat = new ofFloat(new Array[Float](0)) - private val emptyWrappedDouble = new ofDouble(new Array[Double](0)) - private val emptyWrappedUnit = new ofUnit(new Array[Unit](0)) - private val emptyWrappedChar = new ofChar(new Array[Char](0)) - private val emptyWrappedBoolean = new ofBoolean(new Array[Boolean](0)) - final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArray[T] with Serializable { lazy val elemTag = ClassTag[T](array.getClass.getComponentType) def length: Int = array.length @@ -156,8 +134,6 @@ object WrappedArray { case that: ofRef[_] => Arrays.equals(array.asInstanceOf[Array[AnyRef]], that.array.asInstanceOf[Array[AnyRef]]) case _ => super.equals(that) } - protected override def emptyImpl = new ofRef(util.Arrays.copyOf[T](array,0)) - protected override def sliceImpl(from: Int, until: Int) = new ofRef[T](util.Arrays.copyOfRange[T](array, from, until)) } final class ofByte(val array: Array[Byte]) extends WrappedArray[Byte] with Serializable { @@ -170,8 +146,6 @@ object WrappedArray { case that: ofByte => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedByte - protected override def sliceImpl(from: Int, until: Int) = new ofByte(util.Arrays.copyOfRange(array, from, until)) } final class ofShort(val array: Array[Short]) extends WrappedArray[Short] with Serializable { @@ -184,8 +158,6 @@ object WrappedArray { case that: ofShort => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedShort - protected override def sliceImpl(from: Int, until: Int) = new ofShort(util.Arrays.copyOfRange(array, from, until)) } final class ofChar(val array: Array[Char]) extends WrappedArray[Char] with Serializable { @@ -198,8 +170,6 @@ object WrappedArray { case that: ofChar => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedChar - protected override def sliceImpl(from: Int, until: Int) = new ofChar(util.Arrays.copyOfRange(array, from, until)) } final class ofInt(val array: Array[Int]) extends WrappedArray[Int] with Serializable { @@ -212,8 +182,6 @@ object WrappedArray { case that: ofInt => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedInt - protected override def sliceImpl(from: Int, until: Int) = new ofInt(util.Arrays.copyOfRange(array, from, until)) } final class ofLong(val array: Array[Long]) extends WrappedArray[Long] with Serializable { @@ -226,8 +194,6 @@ object WrappedArray { case that: ofLong => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedLong - protected override def sliceImpl(from: Int, until: Int) = new ofLong(util.Arrays.copyOfRange(array, from, until)) } final class ofFloat(val array: Array[Float]) extends WrappedArray[Float] with Serializable { @@ -240,8 +206,6 @@ object WrappedArray { case that: ofFloat => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedFloat - protected override def sliceImpl(from: Int, until: Int) = new ofFloat(util.Arrays.copyOfRange(array, from, until)) } final class ofDouble(val array: Array[Double]) extends WrappedArray[Double] with Serializable { @@ -254,8 +218,6 @@ object WrappedArray { case that: ofDouble => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedDouble - protected override def sliceImpl(from: Int, until: Int) = new ofDouble(util.Arrays.copyOfRange(array, from, until)) } final class ofBoolean(val array: Array[Boolean]) extends WrappedArray[Boolean] with Serializable { @@ -268,8 +230,6 @@ object WrappedArray { case that: ofBoolean => Arrays.equals(array, that.array) case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedBoolean - protected override def sliceImpl(from: Int, until: Int) = new ofBoolean(util.Arrays.copyOfRange(array, from, until)) } final class ofUnit(val array: Array[Unit]) extends WrappedArray[Unit] with Serializable { @@ -282,14 +242,5 @@ object WrappedArray { case that: ofUnit => array.length == that.array.length case _ => super.equals(that) } - protected override def emptyImpl = emptyWrappedUnit - protected override def sliceImpl(from: Int, until: Int) = { - // cant use - // new ofUnit(util.Arrays.copyOfRange[Unit](array, from, until)) - Unit is special and doesnt compile - // cant use util.Arrays.copyOfRange[Unit](repr, from, until) - Unit is special and doesnt compile - val res = new Array[Unit](until-from) - System.arraycopy(repr, from, res, 0, until-from) - new ofUnit(res) - } } } -- cgit v1.2.3