summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala2
-rw-r--r--src/reflect/scala/reflect/internal/ReificationSupport.scala29
-rw-r--r--src/reflect/scala/reflect/internal/TreeGen.scala2
-rw-r--r--test/files/scalacheck/quasiquotes/TermConstructionProps.scala19
-rw-r--r--test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala13
5 files changed, 44 insertions, 21 deletions
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
index 4937bfc35d..481897d0ec 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
@@ -202,6 +202,8 @@ trait Reifiers { self: Quasiquotes =>
// not to cause infinite recursion.
case block @ SyntacticBlock(stats) if block.isInstanceOf[Block] =>
reifyBuildCall(nme.SyntacticBlock, stats)
+ case SyntheticUnit() =>
+ reifyBuildCall(nme.SyntacticBlock, Nil)
case Try(block, catches, finalizer) =>
reifyBuildCall(nme.SyntacticTry, block, catches, finalizer)
case Match(selector, cases) =>
diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala
index ea230a215b..7f345845fe 100644
--- a/src/reflect/scala/reflect/internal/ReificationSupport.scala
+++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala
@@ -94,7 +94,11 @@ trait ReificationSupport { self: SymbolTable =>
def setSymbol[T <: Tree](tree: T, sym: Symbol): T = { tree.setSymbol(sym); tree }
- def toStats(tree: Tree): List[Tree] = SyntacticBlock.unapply(tree).get
+ def toStats(tree: Tree): List[Tree] = tree match {
+ case EmptyTree => Nil
+ case SyntacticBlock(stats) => stats
+ case _ => throw new IllegalArgumentException(s"can't flatten $tree")
+ }
def mkAnnotation(tree: Tree): Tree = tree match {
case SyntacticNew(Nil, SyntacticApplied(SyntacticTypeApplied(_, _), _) :: Nil, noSelfType, Nil) =>
@@ -239,7 +243,7 @@ trait ReificationSupport { self: SymbolTable =>
def unapply(templ: Template): Option[(List[Tree], ValDef, Modifiers, List[List[ValDef]], List[Tree], List[Tree])] = {
val Template(parents, selfType, _) = templ
val tbody = treeInfo.untypecheckedTemplBody(templ)
-
+
def result(ctorMods: Modifiers, vparamss: List[List[ValDef]], edefs: List[Tree], body: List[Tree]) =
Some((parents, selfType, ctorMods, vparamss, edefs, body))
def indexOfCtor(trees: List[Tree]) =
@@ -448,28 +452,25 @@ trait ReificationSupport { self: SymbolTable =>
* block as a list of elements rather than (stats, expr) pair
* it also:
*
- * 1. Treats of q"" (empty tree) as zero-element block.
- *
- * 2. Strips trailing synthetic units which are inserted by the
+ * 1. Strips trailing synthetic units which are inserted by the
* compiler if the block ends with a definition rather
- * than an expression.
+ * than an expression or is empty.
*
- * 3. Matches non-block term trees and recognizes them as
+ * 2. Matches non-block term trees and recognizes them as
* single-element blocks for sake of consistency with
* compiler's default to treat single-element blocks with
- * expressions as just expressions.
+ * expressions as just expressions. The only exception is q""
+ * which is not considered to be a block.
*/
object SyntacticBlock extends SyntacticBlockExtractor {
- def apply(stats: List[Tree]): Tree =
- if (stats.isEmpty) EmptyTree
- else gen.mkBlock(stats)
+ def apply(stats: List[Tree]): Tree = gen.mkBlock(stats)
def unapply(tree: Tree): Option[List[Tree]] = tree match {
case bl @ self.Block(stats, SyntheticUnit()) => Some(treeInfo.untypecheckedBlockBody(bl))
case bl @ self.Block(stats, expr) => Some(treeInfo.untypecheckedBlockBody(bl) :+ expr)
- case EmptyTree => Some(Nil)
- case _ if tree.isTerm => Some(tree :: Nil)
- case _ => None
+ case SyntheticUnit() => Some(Nil)
+ case _ if tree.isTerm && tree.nonEmpty => Some(tree :: Nil)
+ case _ => None
}
}
diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala
index 6011289baf..9066c73393 100644
--- a/src/reflect/scala/reflect/internal/TreeGen.scala
+++ b/src/reflect/scala/reflect/internal/TreeGen.scala
@@ -452,7 +452,7 @@ abstract class TreeGen {
/** Create block of statements `stats` */
def mkBlock(stats: List[Tree]): Tree =
- if (stats.isEmpty) Literal(Constant(()))
+ if (stats.isEmpty) mkSyntheticUnit()
else if (!stats.last.isTerm) Block(stats, mkSyntheticUnit())
else if (stats.length == 1) stats.head
else Block(stats.init, stats.last)
diff --git a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
index 10ce1604b1..fd4d2e9c4b 100644
--- a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
@@ -103,7 +103,7 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") {
def blockInvariant(quote: Tree, trees: List[Tree]) =
quote ≈ (trees match {
- case Nil => q""
+ case Nil => q"{}"
case _ :+ last if !last.isTerm => Block(trees, q"()")
case head :: Nil => head
case init :+ last => Block(init, last)
@@ -277,11 +277,18 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") {
assert(stats ≈ List(q"def x = 2", q"()"))
}
- property("empty-tree as block") = test {
- val q"{ ..$stats1 }" = q" "
- assert(stats1.isEmpty)
- val stats2 = List.empty[Tree]
- assert(q"{ ..$stats2 }" ≈ q"")
+ property("empty-tree is not a block") = test {
+ assertThrows[MatchError] {
+ val q"{ ..$stats1 }" = q" "
+ }
+ }
+
+ property("empty block is synthetic unit") = test {
+ val q"()" = q"{}"
+ val q"{..$stats}" = q"{}"
+ assert(stats.isEmpty)
+ assertEqAst(q"{..$stats}", "{}")
+ assertEqAst(q"{..$stats}", "()")
}
property("consistent variable order") = test {
diff --git a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
index c77946c291..e96d1186f7 100644
--- a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
@@ -186,4 +186,17 @@ object TermDeconstructionProps extends QuasiquoteProperties("term deconstruction
assert(init ≈ List(q"a", q"b"))
assert(last ≈ q"c")
}
+
+ property("si-8275 c") = test {
+ val cq"_ => ..$stats" = cq"_ =>"
+ assert(stats.isEmpty)
+ assertEqAst(q"{ case _ => ..$stats }", "{ case _ => }")
+ }
+
+ property("can't flatten type into block") = test {
+ assertThrows[IllegalArgumentException] {
+ val tpt = tq"List[Int]"
+ q"..$tpt; ()"
+ }
+ }
}