diff options
Diffstat (limited to 'src/reflect')
-rw-r--r-- | src/reflect/scala/reflect/internal/Internals.scala | 14 | ||||
-rw-r--r-- | src/reflect/scala/reflect/macros/Universe.scala | 16 |
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 |