summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/internal/Internals.scala14
-rw-r--r--src/reflect/scala/reflect/macros/Universe.scala16
2 files changed, 30 insertions, 0 deletions
diff --git a/src/reflect/scala/reflect/internal/Internals.scala b/src/reflect/scala/reflect/internal/Internals.scala
index 9f503f66c3..cd2017e693 100644
--- a/src/reflect/scala/reflect/internal/Internals.scala
+++ b/src/reflect/scala/reflect/internal/Internals.scala
@@ -58,6 +58,20 @@ trait Internals extends api.Internals {
def typeDef(sym: Symbol): TypeDef = self.TypeDef(sym)
def labelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef = self.LabelDef(sym, params, rhs)
+ def changeOwner(tree: Tree, prev: Symbol, next: Symbol): tree.type = {
+ object changeOwnerAndModuleClassTraverser extends ChangeOwnerTraverser(prev, next) {
+ override def traverse(tree: Tree) {
+ tree match {
+ case _: DefTree => change(tree.symbol.moduleClass)
+ case _ => // do nothing
+ }
+ super.traverse(tree)
+ }
+ }
+ changeOwnerAndModuleClassTraverser.traverse(tree)
+ tree
+ }
+
lazy val gen = self.treeBuild
def isFreeTerm(symbol: Symbol): Boolean = symbol.isFreeTerm
diff --git a/src/reflect/scala/reflect/macros/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala
index 9840295c95..15fd6bad99 100644
--- a/src/reflect/scala/reflect/macros/Universe.scala
+++ b/src/reflect/scala/reflect/macros/Universe.scala
@@ -25,6 +25,22 @@ abstract class Universe extends scala.reflect.api.Universe {
/** @inheritdoc */
trait MacroInternalApi extends InternalApi {
+ /** Collects all the symbols defined by subtrees of `tree` that are owned by `prev`,
+ * and then changes their owner to point to `next`.
+ *
+ * This is an essential tool to battle owner chain corruption when moving trees
+ * from one lexical context to another. Whenever you take an attributed tree that
+ * has been typechecked under the Context owned by some symbol (let's call it `x`)
+ * and splice it elsewhere, into the Context owned by another symbol (let's call it `y`),
+ * it is imperative that you either call `untypecheck` or do `changeOwner(tree, x, y)`.
+ *
+ * Since at the moment `untypecheck` has fundamental problem that can sometimes lead to tree corruption,
+ * `changeOwner` becomes an indispensible tool in building 100% robust macros.
+ * Future versions of the reflection API might obviate the need in taking care of
+ * these low-level details, but at the moment this is what we've got.
+ */
+ def changeOwner(tree: Tree, prev: Symbol, next: Symbol): tree.type
+
/** Advanced tree factories */
val gen: TreeGen