diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-01-03 02:32:45 -0800 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-01-03 02:32:45 -0800 |
commit | 64e214348a2d41cb278062fb471084cc191d9a9d (patch) | |
tree | c5fd5341e2cec33c55df6101a788f3df7f12900a /src | |
parent | 718b26baa6113bef9ce3ebc7c439e099615db78d (diff) | |
parent | 71a2102a2df3721e0b8d0a9a5e87d01eb849dadd (diff) | |
download | scala-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')
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" |