summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bincompat-backward.whitelist.conf17
-rw-r--r--bincompat-forward.whitelist.conf29
-rw-r--r--src/compiler/scala/reflect/macros/contexts/Names.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala19
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Holes.scala6
-rw-r--r--src/library/scala/collection/Iterator.scala10
-rw-r--r--src/reflect/scala/reflect/api/Mirror.scala18
-rw-r--r--src/reflect/scala/reflect/api/StandardLiftables.scala1
-rw-r--r--src/reflect/scala/reflect/internal/Mirrors.scala2
-rw-r--r--test/files/neg/t8431.check27
-rw-r--r--test/files/neg/t8431.scala63
-rw-r--r--test/files/run/mirror_symbolof_x.check13
-rw-r--r--test/files/run/mirror_symbolof_x.scala43
-rw-r--r--test/files/run/t8425.check1
-rw-r--r--test/files/run/t8425/Macros_1.scala12
-rw-r--r--test/files/run/t8425/Test_2.scala3
-rw-r--r--test/files/run/t8428.scala12
-rw-r--r--test/files/scalacheck/quasiquotes/ErrorProps.scala31
-rw-r--r--test/files/scalacheck/quasiquotes/LiftableProps.scala8
-rw-r--r--versions.properties18
20 files changed, 303 insertions, 33 deletions
diff --git a/bincompat-backward.whitelist.conf b/bincompat-backward.whitelist.conf
index ae31c286f3..b799b17c21 100644
--- a/bincompat-backward.whitelist.conf
+++ b/bincompat-backward.whitelist.conf
@@ -102,6 +102,11 @@ filter {
matchName="scala.collection.mutable.ArrayOps#ofDouble.unzip3"
problemName=IncompatibleMethTypeProblem
},
+ // see SI-8200
+ {
+ matchName="scala.reflect.api.StandardLiftables#StandardLiftableInstances.liftTree"
+ problemName=MissingMethodProblem
+ },
// see SI-8331
{
matchName="scala.reflect.api.Internals#ReificationSupportApi#SyntacticTypeAppliedExtractor.unapply"
@@ -127,6 +132,18 @@ filter {
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticPartialFunction"
problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Mirror.symbolOf"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Mirror.typeOf"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Mirror.weakTypeOf"
+ problemName=MissingMethodProblem
}
]
}
diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf
index 3eba1effc1..58bf98a173 100644
--- a/bincompat-forward.whitelist.conf
+++ b/bincompat-forward.whitelist.conf
@@ -102,7 +102,16 @@ filter {
matchName="scala.collection.mutable.ArrayOps#ofDouble.unzip3"
problemName=IncompatibleMethTypeProblem
},
- // see SI-8331
+ // see SI-8200
+ {
+ matchName="scala.reflect.api.Liftables#Liftable.liftTree"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.StandardLiftables#StandardLiftableInstances.liftTree"
+ problemName=MissingMethodProblem
+ },
+ // see SI-8331
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSelectType"
problemName=MissingMethodProblem
@@ -139,6 +148,22 @@ filter {
{
matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticPartialFunction"
problemName=MissingMethodProblem
- }
+ },
+ {
+ matchName="scala.collection.Iterator#ConcatIterator.this"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Mirror.symbolOf"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Mirror.typeOf"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Mirror.weakTypeOf"
+ 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/compiler/scala/tools/reflect/quasiquotes/Holes.scala b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala
index 8376fca4ad..55a28f9f20 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Holes.scala
@@ -78,8 +78,10 @@ trait Holes { self: Quasiquotes =>
val (strippedTpe, tpe): (Type, Type) = {
val (strippedRank, strippedTpe) = stripIterable(unquotee.tpe, limit = Some(annotatedRank))
if (isBottomType(strippedTpe)) cantSplice()
- else if (isNativeType(strippedTpe)) (strippedTpe, iterableTypeFromRank(annotatedRank, strippedTpe))
- else if (isLiftableType(strippedTpe)) (strippedTpe, iterableTypeFromRank(annotatedRank, treeType))
+ else if (isNativeType(strippedTpe)) {
+ if (strippedRank != NoDot && !(strippedTpe <:< treeType) && !isLiftableType(strippedTpe)) cantSplice()
+ else (strippedTpe, iterableTypeFromRank(annotatedRank, strippedTpe))
+ } else if (isLiftableType(strippedTpe)) (strippedTpe, iterableTypeFromRank(annotatedRank, treeType))
else cantSplice()
}
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/src/reflect/scala/reflect/api/Mirror.scala b/src/reflect/scala/reflect/api/Mirror.scala
index da3afd89ff..318fdb369a 100644
--- a/src/reflect/scala/reflect/api/Mirror.scala
+++ b/src/reflect/scala/reflect/api/Mirror.scala
@@ -118,4 +118,22 @@ abstract class Mirror[U <: Universe with Singleton] {
* @group Mirror
*/
def staticPackage(fullName: String): U#ModuleSymbol
+
+ /**
+ * Shortcut for `implicitly[WeakTypeTag[T]].tpe`
+ * @group TypeTags
+ */
+ def weakTypeOf[T: universe.WeakTypeTag]: U#Type = universe.weakTypeTag[T].in(this).tpe
+
+ /**
+ * Shortcut for `implicitly[TypeTag[T]].tpe`
+ * @group TypeTags
+ */
+ def typeOf[T: universe.TypeTag]: U#Type = universe.typeTag[T].in(this).tpe
+
+ /**
+ * Type symbol of `x` as derived from a type tag.
+ * @group TypeTags
+ */
+ def symbolOf[T: universe.WeakTypeTag]: U#TypeSymbol
}
diff --git a/src/reflect/scala/reflect/api/StandardLiftables.scala b/src/reflect/scala/reflect/api/StandardLiftables.scala
index af11de46ce..66ac62cc9e 100644
--- a/src/reflect/scala/reflect/api/StandardLiftables.scala
+++ b/src/reflect/scala/reflect/api/StandardLiftables.scala
@@ -27,6 +27,7 @@ trait StandardLiftables { self: Universe =>
callScala(stdnme.Symbol)(Literal(Constant(v.name)) :: Nil)
}
+ implicit def liftTree[T <: Tree]: Liftable[T] = Liftable { identity }
implicit def liftName[T <: Name]: Liftable[T] = Liftable { name => Ident(name) }
implicit def liftExpr[T <: Expr[_]]: Liftable[T] = Liftable { expr => expr.tree }
implicit def liftType[T <: Type]: Liftable[T] = Liftable { tpe => TypeTree(tpe) }
diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala
index 7065a8cd6d..4a35e024de 100644
--- a/src/reflect/scala/reflect/internal/Mirrors.scala
+++ b/src/reflect/scala/reflect/internal/Mirrors.scala
@@ -30,6 +30,8 @@ trait Mirrors extends api.Mirrors {
val EmptyPackageClass: ClassSymbol
val EmptyPackage: ModuleSymbol
+ def symbolOf[T: universe.WeakTypeTag]: universe.TypeSymbol = universe.weakTypeTag[T].in(this).tpe.typeSymbolDirect.asType
+
def findMemberFromRoot(fullName: Name): Symbol = {
val segs = nme.segments(fullName.toString, fullName.isTermName)
if (segs.isEmpty) NoSymbol
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/mirror_symbolof_x.check b/test/files/run/mirror_symbolof_x.check
new file mode 100644
index 0000000000..cc9cad7a13
--- /dev/null
+++ b/test/files/run/mirror_symbolof_x.check
@@ -0,0 +1,13 @@
+class Int
+object C
+type T
+type Id
+class Nothing
+class Null
+class Int
+object C
+type T
+type Id
+class Nothing
+class Null
+exception: class C not found.
diff --git a/test/files/run/mirror_symbolof_x.scala b/test/files/run/mirror_symbolof_x.scala
new file mode 100644
index 0000000000..8fec301f56
--- /dev/null
+++ b/test/files/run/mirror_symbolof_x.scala
@@ -0,0 +1,43 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{universe => ru}
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.reflect.api.Mirror
+
+class C
+object C
+
+object Test extends App {
+ object test1 {
+ val m = cm
+ type T = Int
+ type Id[X] = X
+ println(m.symbolOf[Int]: ru.TypeSymbol)
+ println(m.symbolOf[C.type]: ru.TypeSymbol)
+ println(m.symbolOf[T]: ru.TypeSymbol)
+ println(m.symbolOf[Id[_]]: ru.TypeSymbol)
+ println(m.symbolOf[Nothing]: ru.TypeSymbol)
+ println(m.symbolOf[Null]: ru.TypeSymbol)
+ }
+
+ object test2 {
+ val m: Mirror[ru.type] = cm
+ type T = Int
+ type Id[X] = X
+ println(m.symbolOf[Int]: ru.TypeSymbol)
+ println(m.symbolOf[C.type]: ru.TypeSymbol)
+ println(m.symbolOf[T]: ru.TypeSymbol)
+ println(m.symbolOf[Id[_]]: ru.TypeSymbol)
+ println(m.symbolOf[Nothing]: ru.TypeSymbol)
+ println(m.symbolOf[Null]: ru.TypeSymbol)
+ }
+
+ object test3 {
+ val m = ru.runtimeMirror(classOf[Int].getClass.getClassLoader)
+ try println(m.symbolOf[C])
+ catch { case ex: ScalaReflectionException => println(s"exception: ${ex.getMessage}") }
+ }
+
+ test1
+ test2
+ test3
+}
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/test/files/scalacheck/quasiquotes/ErrorProps.scala b/test/files/scalacheck/quasiquotes/ErrorProps.scala
index 3d9b27de77..9137fe17d8 100644
--- a/test/files/scalacheck/quasiquotes/ErrorProps.scala
+++ b/test/files/scalacheck/quasiquotes/ErrorProps.scala
@@ -9,9 +9,10 @@ object ErrorProps extends QuasiquoteProperties("errors") {
""")
property("can't unquote with given rank") = fails(
- "Can't unquote List[reflect.runtime.universe.Ident], consider using ..",
+ "Can't unquote List[StringBuilder], consider using .. or providing an implicit instance of Liftable[List[StringBuilder]]",
"""
- val xs = List(q"x", q"x")
+ import java.lang.StringBuilder
+ val xs: List[StringBuilder] = Nil
q"$xs"
""")
@@ -71,9 +72,10 @@ object ErrorProps extends QuasiquoteProperties("errors") {
""")
property("use ... rank or provide liftable") = fails(
- "Can't unquote List[List[reflect.runtime.universe.Ident]], consider using ...",
+ "Can't unquote List[List[StringBuilder]], consider using ... or providing an implicit instance of Liftable[List[List[StringBuilder]]]",
"""
- val xs = List(List(q"x", q"x"))
+ import java.lang.StringBuilder
+ val xs: List[List[StringBuilder]] = Nil
q"$xs"
""")
@@ -172,6 +174,27 @@ object ErrorProps extends QuasiquoteProperties("errors") {
tq"_"
""")
+ property("SI-8420: don't crash on splicing of non-unliftable native type (1)") = fails(
+ "Can't unquote List[reflect.runtime.universe.Symbol] with .., consider omitting the dots or providing an implicit instance of Liftable[reflect.runtime.universe.Symbol]",
+ """
+ val l: List[Symbol] = Nil
+ q"f(..$l)"
+ """)
+
+ property("SI-8420: don't crash on splicing of non-unliftable native type (2)") = fails(
+ "Can't unquote List[reflect.runtime.universe.FlagSet] with .., consider omitting the dots or providing an implicit instance of Liftable[reflect.runtime.universe.FlagSet]",
+ """
+ val l: List[FlagSet] = Nil
+ q"f(..$l)"
+ """)
+
+ property("SI-8420: don't crash on splicing of non-unliftable native type (3)") = fails(
+ "Can't unquote List[reflect.runtime.universe.Modifiers] with .., consider omitting the dots or providing an implicit instance of Liftable[reflect.runtime.universe.Modifiers]",
+ """
+ val l: List[Modifiers] = Nil
+ q"f(..$l)"
+ """)
+
// // Make sure a nice error is reported in this case
// { import Flag._; val mods = NoMods; q"lazy $mods val x: Int" }
}
diff --git a/test/files/scalacheck/quasiquotes/LiftableProps.scala b/test/files/scalacheck/quasiquotes/LiftableProps.scala
index 5d0eeb53c6..29fdea5c89 100644
--- a/test/files/scalacheck/quasiquotes/LiftableProps.scala
+++ b/test/files/scalacheck/quasiquotes/LiftableProps.scala
@@ -88,9 +88,10 @@ object LiftableProps extends QuasiquoteProperties("liftable") {
assert(q"$const" ≈ q"0")
}
+ val immutable = q"$scalapkg.collection.immutable"
+
property("lift list variants") = test {
val lst = List(1, 2)
- val immutable = q"$scalapkg.collection.immutable"
assert(q"$lst" ≈ q"$immutable.List(1, 2)")
assert(q"f(..$lst)" ≈ q"f(1, 2)")
val llst = List(List(1), List(2))
@@ -98,6 +99,11 @@ object LiftableProps extends QuasiquoteProperties("liftable") {
assert(q"f(...$llst)" ≈ q"f(1)(2)")
}
+ property("lift list of tree") = test {
+ val lst = List(q"a", q"b")
+ assert(q"$lst" ≈ q"$immutable.List(a, b)")
+ }
+
property("lift tuple") = test {
assert(q"${(1, 2)}" ≈ q"(1, 2)")
assert(q"${(1, 2, 3)}" ≈ q"(1, 2, 3)")
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)