diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2012-12-25 14:09:33 +0100 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2012-12-25 14:09:33 +0100 |
commit | 48cdfefb95ee43ded08688d6c99a8c3a32d47f18 (patch) | |
tree | 8afef91284098f0e78e9995349b73db3dd716940 /src | |
parent | d2a7aa4ba1c048e52affb0eb2b9167a18dc29c83 (diff) | |
download | scala-48cdfefb95ee43ded08688d6c99a8c3a32d47f18.tar.gz scala-48cdfefb95ee43ded08688d6c99a8c3a32d47f18.tar.bz2 scala-48cdfefb95ee43ded08688d6c99a8c3a32d47f18.zip |
macro expansions are now auto-duplicated
The fix still requires macro developers to be careful about sharing trees
by references, because attributed DefTrees will still bring trouble.
However this is an improvement, because it doesn't make matters worse
and automatically fixes situations similar to one in the test.
A much more thorough discussion with a number of open questions left:
http://groups.google.com/group/scala-internals/browse_thread/thread/492560d941b315cc
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Macros.scala | 8 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Trees.scala | 7 |
2 files changed, 10 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 4d1ab98fa0..86c59bc671 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -691,9 +691,11 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { var expectedTpe = expandee.tpe if (isNullaryInvocation(expandee)) expectedTpe = expectedTpe.finalResultType - var typechecked = typecheck("macro def return type", expanded, expectedTpe) - typechecked = typecheck("expected type", typechecked, pt) - typechecked + // also see http://groups.google.com/group/scala-internals/browse_thread/thread/492560d941b315cc + val expanded0 = duplicateAndKeepPositions(expanded) + val expanded1 = typecheck("macro def return type", expanded0, expectedTpe) + val expanded2 = typecheck("expected type", expanded1, pt) + expanded2 } finally { popMacroContext() } diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 9e737528d2..ae9fca14cb 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -1499,15 +1499,18 @@ trait Trees extends api.Trees { self: SymbolTable => } } - private lazy val duplicator = new Transformer { + private lazy val duplicator = new Duplicator(focusPositions = true) + private class Duplicator(focusPositions: Boolean) extends Transformer { override val treeCopy = newStrictTreeCopier override def transform(t: Tree) = { val t1 = super.transform(t) - if ((t1 ne t) && t1.pos.isRange) t1 setPos t.pos.focus + if ((t1 ne t) && t1.pos.isRange && focusPositions) t1 setPos t.pos.focus t1 } } + def duplicateAndKeepPositions(tree: Tree) = new Duplicator(focusPositions = false) transform tree + // ------ copiers ------------------------------------------- def copyDefDef(tree: Tree)( |