diff options
-rw-r--r-- | bincompat-forward.whitelist.conf | 6 | ||||
-rw-r--r-- | src/compiler/scala/reflect/macros/contexts/Names.scala | 3 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 19 | ||||
-rw-r--r-- | src/library/scala/collection/Iterator.scala | 10 | ||||
-rw-r--r-- | test/files/neg/t8431.check | 27 | ||||
-rw-r--r-- | test/files/neg/t8431.scala | 63 | ||||
-rw-r--r-- | test/files/run/t8425.check | 1 | ||||
-rw-r--r-- | test/files/run/t8425/Macros_1.scala | 12 | ||||
-rw-r--r-- | test/files/run/t8425/Test_2.scala | 3 | ||||
-rw-r--r-- | test/files/run/t8428.scala | 12 | ||||
-rw-r--r-- | versions.properties | 18 |
11 files changed, 149 insertions, 25 deletions
diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index 3eba1effc1..a4cbac4887 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -139,6 +139,10 @@ filter { { matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticPartialFunction" problemName=MissingMethodProblem - } + }, + { + matchName="scala.collection.Iterator#ConcatIterator.this" + problemName=MissingMethodProblem + } ] } diff --git a/src/compiler/scala/reflect/macros/contexts/Names.scala b/src/compiler/scala/reflect/macros/contexts/Names.scala index 299af40b94..5a5bb428b5 100644 --- a/src/compiler/scala/reflect/macros/contexts/Names.scala +++ b/src/compiler/scala/reflect/macros/contexts/Names.scala @@ -33,8 +33,9 @@ trait Names { // // TODO: hopefully SI-7823 will provide an ultimate answer to this problem. // In the meanwhile I will also keep open the original issue: SI-6879 "c.freshName is broken". + val prefix = if (name.endsWith("$")) name else name + "$" // SI-8425 val sortOfUniqueSuffix = freshNameCreator.newName(nme.FRESH_SUFFIX) - name + "$" + sortOfUniqueSuffix + prefix + sortOfUniqueSuffix } def freshName[NameType <: Name](name: NameType): NameType = diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index c8ac3622e2..1a38fcf3a4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -82,7 +82,7 @@ trait Implicits { // `implicitSearchContext.undetparams`, *not* in `context.undetparams` // Here, we copy them up to parent context (analogously to the way the errors are copied above), // and then filter out any which *were* inferred and are part of the substitutor in the implicit search result. - context.undetparams = ((context.undetparams ++ implicitSearchContext.undetparams) filterNot result.subst.from.contains).distinct + context.undetparams = ((context.undetparams ++ result.undetparams) filterNot result.subst.from.contains).distinct if (Statistics.canEnable) Statistics.stopTimer(implicitNanos, start) if (Statistics.canEnable) Statistics.stopCounter(rawTypeImpl, rawTypeStart) @@ -162,8 +162,9 @@ trait Implicits { * @param tree The tree representing the implicit * @param subst A substituter that represents the undetermined type parameters * that were instantiated by the winning implicit. + * @param undetparams undeterminted type parameters */ - class SearchResult(val tree: Tree, val subst: TreeTypeSubstituter) { + class SearchResult(val tree: Tree, val subst: TreeTypeSubstituter, val undetparams: List[Symbol]) { override def toString = "SearchResult(%s, %s)".format(tree, if (subst.isEmpty) "" else subst) @@ -173,16 +174,16 @@ trait Implicits { final def isSuccess = !isFailure } - lazy val SearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter) { + lazy val SearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter, Nil) { override def isFailure = true } - lazy val DivergentSearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter) { + lazy val DivergentSearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter, Nil) { override def isFailure = true override def isDivergent = true } - lazy val AmbiguousSearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter) { + lazy val AmbiguousSearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter, Nil) { override def isFailure = true override def isAmbiguousFailure = true } @@ -719,7 +720,7 @@ trait Implicits { case Some(err) => fail("typing TypeApply reported errors for the implicit tree: " + err.errMsg) case None => - val result = new SearchResult(unsuppressMacroExpansion(itree3), subst) + val result = new SearchResult(unsuppressMacroExpansion(itree3), subst, context.undetparams) if (Statistics.canEnable) Statistics.incCounter(foundImplicits) typingLog("success", s"inferred value of type $ptInstantiated is $result") result @@ -1126,7 +1127,7 @@ trait Implicits { val tree1 = typedPos(pos.focus)(arg) context.firstError match { case Some(err) => processMacroExpansionError(err.errPos, err.errMsg) - case None => new SearchResult(tree1, EmptyTreeTypeSubstituter) + case None => new SearchResult(tree1, EmptyTreeTypeSubstituter, Nil) } } catch { case ex: TypeError => @@ -1196,7 +1197,7 @@ trait Implicits { def findSubManifest(tp: Type) = findManifest(tp, if (full) FullManifestClass else OptManifestClass) def mot(tp0: Type, from: List[Symbol], to: List[Type]): SearchResult = { implicit def wrapResult(tree: Tree): SearchResult = - if (tree == EmptyTree) SearchFailure else new SearchResult(tree, if (from.isEmpty) EmptyTreeTypeSubstituter else new TreeTypeSubstituter(from, to)) + if (tree == EmptyTree) SearchFailure else new SearchResult(tree, if (from.isEmpty) EmptyTreeTypeSubstituter else new TreeTypeSubstituter(from, to), Nil) val tp1 = tp0.dealias tp1 match { @@ -1284,7 +1285,7 @@ trait Implicits { } def wrapResult(tree: Tree): SearchResult = - if (tree == EmptyTree) SearchFailure else new SearchResult(tree, EmptyTreeTypeSubstituter) + if (tree == EmptyTree) SearchFailure else new SearchResult(tree, EmptyTreeTypeSubstituter, Nil) /** Materializes implicits of predefined types (currently, manifests and tags). * Will be replaced by implicit macros once we fix them. diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index 01a0aa3b51..1b496383a3 100644 --- a/src/library/scala/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -165,11 +165,11 @@ object Iterator { /** Avoid stack overflows when applying ++ to lots of iterators by * flattening the unevaluated iterators out into a vector of closures. */ - private[scala] final class ConcatIterator[+A](initial: Vector[() => Iterator[A]]) extends Iterator[A] { - // current set to null when all iterators are exhausted - private[this] var current: Iterator[A] = Iterator.empty + private[scala] final class ConcatIterator[+A](private[this] var current: Iterator[A], initial: Vector[() => Iterator[A]]) extends Iterator[A] { + @deprecated def this(initial: Vector[() => Iterator[A]]) = this(Iterator.empty, initial) // for binary compatibility private[this] var queue: Vector[() => Iterator[A]] = initial // Advance current to the next non-empty iterator + // current is set to null when all iterators are exhausted private[this] def advance(): Boolean = { if (queue.isEmpty) { current = null @@ -185,7 +185,7 @@ object Iterator { def next() = if (hasNext) current.next else Iterator.empty.next override def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] = - new ConcatIterator(queue :+ (() => that.toIterator)) + new ConcatIterator(current, queue :+ (() => that.toIterator)) } private[scala] final class JoinIterator[+A](lhs: Iterator[A], that: => GenTraversableOnce[A]) extends Iterator[A] { @@ -194,7 +194,7 @@ object Iterator { def next = if (lhs.hasNext) lhs.next else rhs.next override def ++[B >: A](that: => GenTraversableOnce[B]) = - new ConcatIterator(Vector(() => this, () => that.toIterator)) + new ConcatIterator(this, Vector(() => that.toIterator)) } } diff --git a/test/files/neg/t8431.check b/test/files/neg/t8431.check new file mode 100644 index 0000000000..75351a8ae7 --- /dev/null +++ b/test/files/neg/t8431.check @@ -0,0 +1,27 @@ +t8431.scala:24: error: type mismatch; + found : CanBuildFrom[Invariant[Nothing]] + required: CanBuildFrom[Invariant[G]] + s.combined // fail + ^ +t8431.scala:24: error: value combined is not a member of Invariant[Nothing] + s.combined // fail + ^ +t8431.scala:35: error: type mismatch; + found : CanBuildFrom[Invariant[Nothing]] + required: CanBuildFrom[Invariant[G]] + s.combined // was okay! + ^ +t8431.scala:35: error: value combined is not a member of Invariant[Nothing] + s.combined // was okay! + ^ +t8431.scala:45: error: type mismatch; + found : CanBuildFrom[Invariant[Nothing]] + required: CanBuildFrom[Invariant[G]] + convert2(s).combined + ^ +t8431.scala:48: error: type mismatch; + found : CanBuildFrom[Invariant[Nothing]] + required: CanBuildFrom[Invariant[G]] + {val c1 = convert2(s); c1.combined} + ^ +6 errors found diff --git a/test/files/neg/t8431.scala b/test/files/neg/t8431.scala new file mode 100644 index 0000000000..032a1f394d --- /dev/null +++ b/test/files/neg/t8431.scala @@ -0,0 +1,63 @@ +trait Covariant[+A] +trait Invariant[A] extends Covariant[A @annotation.unchecked.uncheckedVariance] + +trait Combinable[G] { + def combined = 0 +} + +trait CanBuildFrom[+C] + +object C { + implicit def convert1[G, TRAVONCE[+e] <: Covariant[e]] + (xs: TRAVONCE[G]): Combinable[G] = ??? + + implicit def convert2[G, SET[e] <: Invariant[e]] + (xs: SET[_ <: G]) + (implicit cbf: CanBuildFrom[SET[G]]): Combinable[G] = ??? + + implicit def cbf[A]: CanBuildFrom[Invariant[A]] = ??? +} +// always failed +class Test1 { + import C.{cbf, convert1, convert2} + val s: Invariant[Nothing] = ??? + s.combined // fail +} +// didn't fail, now correctly fails +class Test2 { + import C.{cbf, convert2, convert1} + + val s: Invariant[Nothing] = ??? + + // Non-uniformity with Test1 was due to order of typechecking implicit candidates: + // the last candidate typechecked was the only one that could contribute undetermined type parameters + // to the enclosing context, due to mutation of `Context#undetparam` in `doTypedApply`. + s.combined // was okay! +} + + +class TestExplicit { + import C.{cbf, convert2} + + val s: Invariant[Nothing] = ??? + + // Now the implicit Test fail uniformly as per this explicit conversion + convert2(s).combined + + // Breaking this expression down doesn't make it work. + {val c1 = convert2(s); c1.combined} +} + +// These ones work before and after; infering G=Null doesn't need to contribute an undetermined type param. +class Test3 { + import C.{cbf, convert1, convert2} + val s: Invariant[Null] = ??? + s.combined // okay +} + +class Test4 { + import C.{cbf, convert2, convert1} + + val s: Invariant[Null] = ??? + s.combined // okay +} diff --git a/test/files/run/t8425.check b/test/files/run/t8425.check new file mode 100644 index 0000000000..8379fa0a74 --- /dev/null +++ b/test/files/run/t8425.check @@ -0,0 +1 @@ +List(fresh$macro$1, $macro$2) diff --git a/test/files/run/t8425/Macros_1.scala b/test/files/run/t8425/Macros_1.scala new file mode 100644 index 0000000000..71a96518e8 --- /dev/null +++ b/test/files/run/t8425/Macros_1.scala @@ -0,0 +1,12 @@ +import scala.language.experimental.macros +import scala.reflect.macros.blackbox.Context + +object Macros { + def foo: Unit = macro impl + def impl(c: Context) = { + import c.universe._ + val test1 = c.freshName() + val test2 = c.freshName("$") + q"println(List($test1, $test2))" + } +}
\ No newline at end of file diff --git a/test/files/run/t8425/Test_2.scala b/test/files/run/t8425/Test_2.scala new file mode 100644 index 0000000000..acfddae942 --- /dev/null +++ b/test/files/run/t8425/Test_2.scala @@ -0,0 +1,3 @@ +object Test extends App { + Macros.foo +}
\ No newline at end of file diff --git a/test/files/run/t8428.scala b/test/files/run/t8428.scala new file mode 100644 index 0000000000..7da1207b7b --- /dev/null +++ b/test/files/run/t8428.scala @@ -0,0 +1,12 @@ +object Test extends App { + val xs = List.tabulate(4)(List(_)) + val i = xs.map(_.iterator).reduce { (a,b) => + a.hasNext + a ++ b + } + + val r1 = i.toList + val r2 = xs.flatten.toList + + assert(r1 == r2, r1) +} diff --git a/versions.properties b/versions.properties index 9042c4198b..d92553d68d 100644 --- a/versions.properties +++ b/versions.properties @@ -1,20 +1,20 @@ -#Fri, 28 Feb 2014 07:00:05 +0100 -starr.version=2.11.0-RC1 +#Wed, 19 Mar 2014 03:05:28 +0100 +starr.version=2.11.0-RC3 starr.use.released=1 # These are the versions of the modules that go with this release. # These properties are used during PR validation and in dbuild builds. -scala.binary.version=2.11.0-RC1 +scala.binary.version=2.11.0-RC3 # external modules shipped with distribution: -scala-xml.version.number=1.0.0 -scala-parser-combinators.version.number=1.0.0 -scala-continuations-plugin.version.number=1.0.0 -scala-continuations-library.version.number=1.0.0 -scala-swing.version.number=1.0.0 +scala-xml.version.number=1.0.1 +scala-parser-combinators.version.number=1.0.1 +scala-continuations-plugin.version.number=1.0.1 +scala-continuations-library.version.number=1.0.1 +scala-swing.version.number=1.0.1 # these ship with distribution (and scala-library-all depends on them) -akka-actor.version.number=2.3.0-RC4 +akka-actor.version.number=2.3.0 actors-migration.version.number=1.1.0 # external modules, used internally (not shipped) |