From 55decf733eb361c235ef1bd9039e5c6226202a96 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Thu, 27 Jun 2013 17:09:39 +0200 Subject: makes it more convenient to work with SuppressMacroExpansionAttachment --- bincompat-backward.whitelist.conf | 12 +++++++++ bincompat-forward.whitelist.conf | 24 +++++++++++++++++ .../scala/tools/nsc/typechecker/Typers.scala | 4 +-- .../scala/reflect/internal/StdAttachments.scala | 31 ++++++++++++++++++++++ 4 files changed, 69 insertions(+), 2 deletions(-) diff --git a/bincompat-backward.whitelist.conf b/bincompat-backward.whitelist.conf index 2ef4ae1cc1..267631f908 100644 --- a/bincompat-backward.whitelist.conf +++ b/bincompat-backward.whitelist.conf @@ -227,6 +227,18 @@ filter { { matchName="scala.reflect.internal.Definitions#DefinitionsClass.primitiveGetClassMethods" problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.StdAttachments.unsuppressMacroExpansion" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.StdAttachments.suppressMacroExpansion" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.StdAttachments.isMacroExpansionSuppressed" + problemName=MissingMethodProblem } ] } diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index 284e0809a8..ec7e2fb6ba 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -479,6 +479,30 @@ filter { { matchName="scala.reflect.internal.Definitions#DefinitionsClass.primitiveGetClassMethods" problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.StdAttachments.unsuppressMacroExpansion" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.StdAttachments.suppressMacroExpansion" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.StdAttachments.isMacroExpansionSuppressed" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.SymbolTable.unsuppressMacroExpansion" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.SymbolTable.suppressMacroExpansion" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.SymbolTable.isMacroExpansionSuppressed" + problemName=MissingMethodProblem } ] } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 29cd3d4bfa..ecbab41db3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1147,7 +1147,7 @@ trait Typers extends Modes with Adaptations with Tags { else if ( inExprModeButNot(mode, FUNmode) && !tree.isDef && // typechecking application tree.symbol != null && tree.symbol.isTermMacro && // of a macro - !tree.attachments.get[SuppressMacroExpansionAttachment.type].isDefined) + !isMacroExpansionSuppressed(tree)) macroExpand(this, tree, mode, pt) else if ((mode & (PATTERNmode | FUNmode)) == (PATTERNmode | FUNmode)) adaptConstrPattern() @@ -5352,7 +5352,7 @@ trait Typers extends Modes with Adaptations with Tags { // that typecheck must not trigger macro expansions, so we explicitly prohibit them // however we cannot do `context.withMacrosDisabled` // because `expr` might contain nested macro calls (see SI-6673) - val exprTyped = typed1(expr updateAttachment SuppressMacroExpansionAttachment, mode, pt) + val exprTyped = typed1(suppressMacroExpansion(expr), mode, pt) exprTyped match { case macroDef if macroDef.symbol != null && macroDef.symbol.isTermMacro && !macroDef.symbol.isErroneous => MacroEtaError(exprTyped) diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala index b782353ed3..539d19140c 100644 --- a/src/reflect/scala/reflect/internal/StdAttachments.scala +++ b/src/reflect/scala/reflect/internal/StdAttachments.scala @@ -42,4 +42,35 @@ trait StdAttachments { * (but think thrice before using that API - see the discussion at https://github.com/scala/scala/pull/1639). */ case object SuppressMacroExpansionAttachment + + /** Suppresses macro expansion of the tree by putting SuppressMacroExpansionAttachment on it. + */ + def suppressMacroExpansion(tree: Tree) = tree.updateAttachment(SuppressMacroExpansionAttachment) + + /** Unsuppresses macro expansion of the tree by removing SuppressMacroExpansionAttachment from it and its children. + */ + def unsuppressMacroExpansion(tree: Tree): Tree = { + tree.removeAttachment[SuppressMacroExpansionAttachment.type] + tree match { + // see the comment to `isMacroExpansionSuppressed` to learn why we need + // a special traversal strategy here + case Apply(fn, _) => unsuppressMacroExpansion(fn) + case TypeApply(fn, _) => unsuppressMacroExpansion(fn) + case _ => // do nothing + } + tree + } + + /** Determines whether a tree should not be expanded, because someone has put SuppressMacroExpansionAttachment on it or one of its children. + */ + def isMacroExpansionSuppressed(tree: Tree): Boolean = + if (tree.attachments.get[SuppressMacroExpansionAttachment.type].isDefined) true + else tree match { + // we have to account for the fact that during typechecking an expandee might become wrapped, + // i.e. surrounded by an inferred implicit argument application or by an inferred type argument application. + // in that case the expandee itself will no longer be suppressed and we need to look at the core + case Apply(fn, _) => isMacroExpansionSuppressed(fn) + case TypeApply(fn, _) => isMacroExpansionSuppressed(fn) + case _ => false + } } -- cgit v1.2.3