summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala29
-rw-r--r--src/reflect/scala/reflect/api/BuildUtils.scala4
-rw-r--r--src/reflect/scala/reflect/internal/BuildUtils.scala4
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala2
-rw-r--r--test/files/jvm/t5471.check (renamed from test/files/jvm/si5471.check)0
-rw-r--r--test/files/jvm/t5471.scala (renamed from test/files/jvm/si5471.scala)0
-rw-r--r--test/files/run/reify_renamed_term_t5841.check (renamed from test/files/run/reify_renamed_term_si5841.check)0
-rw-r--r--test/files/run/reify_renamed_term_t5841.scala (renamed from test/files/run/reify_renamed_term_si5841.scala)0
-rw-r--r--test/files/run/t4750.check (renamed from test/files/run/si4750.check)0
-rw-r--r--test/files/run/t4750.scala (renamed from test/files/run/si4750.scala)0
-rw-r--r--test/files/run/t5045.check (renamed from test/files/run/si5045.check)0
-rw-r--r--test/files/run/t5045.scala (renamed from test/files/run/si5045.scala)0
-rw-r--r--test/files/run/t8047.check7
-rw-r--r--test/files/run/t8047.scala31
-rw-r--r--test/files/scalacheck/t4147.scala (renamed from test/files/scalacheck/si4147.scala)0
15 files changed, 64 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
index 6d7aafe266..87ab52414c 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
@@ -32,8 +32,16 @@ trait Reifiers { self: Quasiquotes =>
var nameMap = collection.mutable.HashMap.empty[Name, Set[TermName]].withDefault { _ => Set() }
/** Wraps expressions into:
- * a sequence of nested withFreshTermName/withFreshTypeName calls which are required
- * to force regeneration of randomly generated names on every evaluation of quasiquote.
+ * a block which starts with a sequence of vals that correspond
+ * to fresh names that has to be created at evaluation of the quasiquote
+ * and ends with reified tree:
+ *
+ * {
+ * val name$1: universe.TermName = universe.build.freshTermName(prefix1)
+ * ...
+ * val name$N: universe.TermName = universe.build.freshTermName(prefixN)
+ * tree
+ * }
*
* Wraps patterns into:
* a call into anonymous class' unapply method required by unapply macro expansion:
@@ -50,15 +58,18 @@ trait Reifiers { self: Quasiquotes =>
*/
def wrap(tree: Tree) =
if (isReifyingExpressions) {
- nameMap.foldLeft(tree) {
- case (t, (origname, names)) =>
+ val freshdefs = nameMap.iterator.map {
+ case (origname, names) =>
assert(names.size == 1)
val FreshName(prefix) = origname
- val ctor = TermName("withFresh" + (if (origname.isTermName) "TermName" else "TypeName"))
- // q"$u.build.$ctor($prefix) { ${names.head} => $t }"
- Apply(Apply(Select(Select(u, nme.build), ctor), List(Literal(Constant(prefix)))),
- List(Function(List(ValDef(Modifiers(PARAM), names.head, TypeTree(), EmptyTree)), t)))
- }
+ val nameTypeName = if (origname.isTermName) tpnme.TermName else tpnme.TypeName
+ val freshName = if (origname.isTermName) nme.freshTermName else nme.freshTypeName
+ // q"val ${names.head}: $u.$nameTypeName = $u.build.$freshName($prefix)"
+ ValDef(NoMods, names.head, Select(u, nameTypeName),
+ Apply(Select(Select(u, nme.build), freshName), Literal(Constant(prefix)) :: Nil))
+ }.toList
+ // q"..$freshdefs; $tree"
+ SyntacticBlock(freshdefs :+ tree)
} else {
val freevars = holeMap.toList.map { case (name, _) => Ident(name) }
val isVarPattern = tree match { case Bind(name, Ident(nme.WILDCARD)) => true case _ => false }
diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala
index 9baf3ec179..6971175f88 100644
--- a/src/reflect/scala/reflect/api/BuildUtils.scala
+++ b/src/reflect/scala/reflect/api/BuildUtils.scala
@@ -90,9 +90,9 @@ private[reflect] trait BuildUtils { self: Universe =>
def RefTree(qual: Tree, sym: Symbol): Tree
- def withFreshTermName[T](prefix: String)(f: TermName => T): T
+ def freshTermName(prefix: String): TermName
- def withFreshTypeName[T](prefix: String)(f: TypeName => T): T
+ def freshTypeName(prefix: String): TypeName
val ScalaDot: ScalaDotExtractor
diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala
index 13c2268227..0a81bfa2a5 100644
--- a/src/reflect/scala/reflect/internal/BuildUtils.scala
+++ b/src/reflect/scala/reflect/internal/BuildUtils.scala
@@ -134,9 +134,9 @@ trait BuildUtils { self: SymbolTable =>
def RefTree(qual: Tree, sym: Symbol) = self.RefTree(qual, sym.name) setSymbol sym
- def withFreshTermName[T](prefix: String)(f: TermName => T): T = f(freshTermName(prefix))
+ def freshTermName(prefix: String): TermName = self.freshTermName(prefix)
- def withFreshTypeName[T](prefix: String)(f: TypeName => T): T = f(freshTypeName(prefix))
+ def freshTypeName(prefix: String): TypeName = self.freshTypeName(prefix)
protected implicit def fresh: FreshNameCreator = self.currentFreshNameCreator
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 111adc1c28..ea6afa7349 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -674,6 +674,8 @@ trait StdNames {
val find_ : NameType = "find"
val flatMap: NameType = "flatMap"
val foreach: NameType = "foreach"
+ val freshTermName: NameType = "freshTermName"
+ val freshTypeName: NameType = "freshTypeName"
val get: NameType = "get"
val hashCode_ : NameType = "hashCode"
val hash_ : NameType = "hash"
diff --git a/test/files/jvm/si5471.check b/test/files/jvm/t5471.check
index bb101b641b..bb101b641b 100644
--- a/test/files/jvm/si5471.check
+++ b/test/files/jvm/t5471.check
diff --git a/test/files/jvm/si5471.scala b/test/files/jvm/t5471.scala
index 2efd869b61..2efd869b61 100644
--- a/test/files/jvm/si5471.scala
+++ b/test/files/jvm/t5471.scala
diff --git a/test/files/run/reify_renamed_term_si5841.check b/test/files/run/reify_renamed_term_t5841.check
index 6031277b76..6031277b76 100644
--- a/test/files/run/reify_renamed_term_si5841.check
+++ b/test/files/run/reify_renamed_term_t5841.check
diff --git a/test/files/run/reify_renamed_term_si5841.scala b/test/files/run/reify_renamed_term_t5841.scala
index ef18d650bf..ef18d650bf 100644
--- a/test/files/run/reify_renamed_term_si5841.scala
+++ b/test/files/run/reify_renamed_term_t5841.scala
diff --git a/test/files/run/si4750.check b/test/files/run/t4750.check
index bf55f70df3..bf55f70df3 100644
--- a/test/files/run/si4750.check
+++ b/test/files/run/t4750.check
diff --git a/test/files/run/si4750.scala b/test/files/run/t4750.scala
index 96d2c4fec7..96d2c4fec7 100644
--- a/test/files/run/si4750.scala
+++ b/test/files/run/t4750.scala
diff --git a/test/files/run/si5045.check b/test/files/run/t5045.check
index 7e9c1961b7..7e9c1961b7 100644
--- a/test/files/run/si5045.check
+++ b/test/files/run/t5045.check
diff --git a/test/files/run/si5045.scala b/test/files/run/t5045.scala
index b0c3a4ddc4..b0c3a4ddc4 100644
--- a/test/files/run/si5045.scala
+++ b/test/files/run/t5045.scala
diff --git a/test/files/run/t8047.check b/test/files/run/t8047.check
new file mode 100644
index 0000000000..a6b83a4a16
--- /dev/null
+++ b/test/files/run/t8047.check
@@ -0,0 +1,7 @@
+doWhile$1(){
+ 1;
+ if (true)
+ doWhile$1()
+ else
+ ()
+}
diff --git a/test/files/run/t8047.scala b/test/files/run/t8047.scala
new file mode 100644
index 0000000000..f5660541e8
--- /dev/null
+++ b/test/files/run/t8047.scala
@@ -0,0 +1,31 @@
+object Test extends App {
+ import scala.reflect.runtime.universe._
+ //
+ // x's owner is outer Test scope. Previosly the quasiquote expansion
+ // looked like:
+ //
+ // object Test {
+ // build.withFreshTermName("doWhile")(n =>
+ // LabelDef(n, List(),
+ // Block(
+ // List({ val x = 1; x }),
+ // If(Literal(Constant(true)), Apply(Ident(n), List()), Literal(Constant(())))))
+ // }
+ //
+ // Here the proper owner is anonymous function, not the Test. Hence
+ // symbol corruption. In new encoding this is represented as:
+ //
+ // object Test {
+ // {
+ // val n = build.freshTermName("doWhile")
+ // LabelDef(n, List(),
+ // Block(
+ // List({ val x = 1; x }),
+ // If(Literal(Constant(true)), Apply(Ident(n), List()), Literal(Constant(()))))
+ // }
+ // }
+ //
+ // Owner stays the same and life is good again.
+ //
+ println(q"do ${ val x = 1; x } while(true)")
+}
diff --git a/test/files/scalacheck/si4147.scala b/test/files/scalacheck/t4147.scala
index 72f6e9afd5..72f6e9afd5 100644
--- a/test/files/scalacheck/si4147.scala
+++ b/test/files/scalacheck/t4147.scala