summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2014-01-03 02:32:45 -0800
committerJason Zaugg <jzaugg@gmail.com>2014-01-03 02:32:45 -0800
commit64e214348a2d41cb278062fb471084cc191d9a9d (patch)
treec5fd5341e2cec33c55df6101a788f3df7f12900a /src
parent718b26baa6113bef9ce3ebc7c439e099615db78d (diff)
parent71a2102a2df3721e0b8d0a9a5e87d01eb849dadd (diff)
downloadscala-64e214348a2d41cb278062fb471084cc191d9a9d.tar.gz
scala-64e214348a2d41cb278062fb471084cc191d9a9d.tar.bz2
scala-64e214348a2d41cb278062fb471084cc191d9a9d.zip
Merge pull request #3245 from densh/si/8047
SI-8047 change fresh name encoding in quasiquotes to avoid symbol owner corruption
Diffstat (limited to 'src')
-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
4 files changed, 26 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"