From 1f3319c83721401e31642c1515bd9be7c567abc1 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 6 Aug 2014 10:02:00 +1000 Subject: SI-8781 Avoid double-expansion under -Ymacro-expand:discard This mode of macro expansion is used by the presentation compiler to leave the original macro applications ("expandees") in the type checked trees, annotated with the types of the expansions. However, under some circumstances involving implicits, we would re-expand the macro. If the macro wasn't stable, this could lead to a type mismatch. The originally reported problem was with the shapeless `mkSingletonOps` macro. Its expansion had the type of a freshly-named class local to the expansion. Upon the re-expansion, a new class was generated, which lead to errors like: client/Client.scala:4: error: type mismatch; found : fresh$macro$2 required: fresh$macro$1 This commit suppressed re-expansion of the expandee by use of the existing, tree attachment driven mechanism. --- src/compiler/scala/tools/nsc/typechecker/Macros.scala | 5 ++++- test/files/pos/t8781/Macro_1.scala | 13 +++++++++++++ test/files/pos/t8781/Test_2.flags | 1 + test/files/pos/t8781/Test_2.scala | 5 +++++ 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 test/files/pos/t8781/Macro_1.scala create mode 100644 test/files/pos/t8781/Test_2.flags create mode 100644 test/files/pos/t8781/Test_2.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 9c22688581..33d3432ae2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -576,7 +576,10 @@ trait Macros extends MacroRuntimes with Traces with Helpers { // also see http://groups.google.com/group/scala-internals/browse_thread/thread/492560d941b315cc val expanded1 = try onSuccess(duplicateAndKeepPositions(expanded)) finally popMacroContext() if (!hasMacroExpansionAttachment(expanded1)) linkExpandeeAndExpanded(expandee, expanded1) - if (settings.Ymacroexpand.value == settings.MacroExpand.Discard) expandee.setType(expanded1.tpe) + if (settings.Ymacroexpand.value == settings.MacroExpand.Discard) { + suppressMacroExpansion(expandee) + expandee.setType(expanded1.tpe) + } else expanded1 case Fallback(fallback) => onFallback(fallback) case Delayed(delayed) => onDelayed(delayed) diff --git a/test/files/pos/t8781/Macro_1.scala b/test/files/pos/t8781/Macro_1.scala new file mode 100644 index 0000000000..ecd9c5e8d5 --- /dev/null +++ b/test/files/pos/t8781/Macro_1.scala @@ -0,0 +1,13 @@ +import scala.reflect.macros.whitebox.Context +import language.experimental.macros + +object Macros { + def impl(c: Context) = { + import c.universe._ + val name = TypeName(c.freshName()) + q"class $name extends T; new $name" + } + def fresh: Any = macro impl +} + +trait T diff --git a/test/files/pos/t8781/Test_2.flags b/test/files/pos/t8781/Test_2.flags new file mode 100644 index 0000000000..24e2109690 --- /dev/null +++ b/test/files/pos/t8781/Test_2.flags @@ -0,0 +1 @@ +-Ymacro-expand:discard -Ystop-after:typer diff --git a/test/files/pos/t8781/Test_2.scala b/test/files/pos/t8781/Test_2.scala new file mode 100644 index 0000000000..3ca6406599 --- /dev/null +++ b/test/files/pos/t8781/Test_2.scala @@ -0,0 +1,5 @@ +object Test { + implicit class RichT(t: T) { def augmented = "" } + + Macros.fresh.augmented +} -- cgit v1.2.3