summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-11-16 14:13:33 +0100
committerEugene Burmako <xeno.by@gmail.com>2012-11-18 21:13:43 +0100
commit907d6ea06ee2e2116dc24838b73990dca3d4c651 (patch)
tree164959bc1c2fc2067526d699c183c39a961015bc /src/compiler/scala/tools/nsc/typechecker/Typers.scala
parent1a6c8597109a9eee122d01c142d8955a14f704c8 (diff)
downloadscala-907d6ea06ee2e2116dc24838b73990dca3d4c651.tar.gz
scala-907d6ea06ee2e2116dc24838b73990dca3d4c651.tar.bz2
scala-907d6ea06ee2e2116dc24838b73990dca3d4c651.zip
SI-6673 fixes macro problems with eta expansions
Eta expansions previously caused the typer to disable macros. That was done in order to detect eta expansion of macro defs and show the user an appropriate error message. Macros were disabled because to find out whether we're expanding a macro def, we need to get its symbol, and to get a symbol of something we need to typecheck that something. However typechecking automatically expands macros, so, unless we disable macros, after a typecheck we won't be able to analyze macro occurrences anymore. Unfortunately this solution has a fatal flaw. By disabling macros we not only prevent the eta-expandee from macro expanding, but also all the subtrees of that eta-expandee (see SI-6673). This commit adds a mechanism for fine-grained control over macro expansion. Now it's possible to prohibit only the node, but not its children from macro expanding.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala9
1 files changed, 5 insertions, 4 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index df3731794a..789211fa98 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1113,7 +1113,8 @@ trait Typers extends Modes with Adaptations with Tags {
adaptType()
else if (
inExprModeButNot(mode, FUNmode) && !tree.isDef && // typechecking application
- tree.symbol != null && tree.symbol.isTermMacro) // of a macro
+ tree.symbol != null && tree.symbol.isTermMacro && // of a macro
+ !tree.attachments.get[SuppressMacroExpansionAttachment.type].isDefined)
macroExpand(this, tree, mode, pt)
else if ((mode & (PATTERNmode | FUNmode)) == (PATTERNmode | FUNmode))
adaptConstrPattern()
@@ -5215,9 +5216,9 @@ trait Typers extends Modes with Adaptations with Tags {
// find out whether the programmer is trying to eta-expand a macro def
// to do that we need to typecheck the tree first (we need a symbol of the eta-expandee)
// that typecheck must not trigger macro expansions, so we explicitly prohibit them
- // Q: "but, " - you may ask - ", `typed1` doesn't call adapt, which does macro expansion, so why explicit check?"
- // A: solely for robustness reasons. this mechanism might change in the future, which might break unprotected code
- val exprTyped = context.withMacrosDisabled(typed1(expr, mode, pt))
+ // however we cannot do `context.withMacrosDisabled`
+ // because `expr` might contain nested macro calls (see SI-6673)
+ val exprTyped = typed1(expr updateAttachment SuppressMacroExpansionAttachment, mode, pt)
exprTyped match {
case macroDef if macroDef.symbol != null && macroDef.symbol.isTermMacro && !macroDef.symbol.isErroneous =>
MacroEtaError(exprTyped)