Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

hooks for naming and synthesis in Namers.scala and Typers.scala

Interestingly enough, despite of the implementation surface being
quite noticeable, it is enough to hijack just `enterSym` and typechecking
of stats for packages, templates and blocks in order to enable macro annotations.
That and `ensureCompanionObject`, which I couldn't abstract away so far.

An architectural note: given that a hooked method is called `X`,
there are two implementations of this method. `pluginsX` is defined in
AnalyzerPlugins.scala and lets macro plugins customize `X`.
`standardX` is defined next to `X` and provides a default implementation.
Finally `X` is changed to trivially forward to `pluginsX`.

Existing and future callers of `X` now can be completely oblivious of the
introduced hooks, because calls to `X` will continue working and will be
correctly hooked. This makes the infrastructure more robust.

The only downside is that in case when a macro plugin wants to call
into the default implementation, it needs to call `standardX`, because
`X` will lead to a stack overflow. However, in my opinion this not a big
problem, because such failures are load and clear + for every `pluginsX`
we actually provide documentation that says what is its standard impl is.
  • Loading branch information...
commit 87913661e199e3894190b7b8aa0900d7237feec0 1 parent 4d92aec
@xeno-by xeno-by authored
View
7 src/compiler/scala/reflect/macros/runtime/MacroRuntimes.scala
@@ -19,8 +19,13 @@ trait MacroRuntimes extends JavaReflectionRuntimes with ScalaReflectionRuntimes
* @return Requested runtime if macro implementation can be loaded successfully from either of the mirrors,
* `null` otherwise.
*/
+ def macroRuntime(expandee: Tree): MacroRuntime = pluginsMacroRuntime(expandee)
+
+ /** Default implementation of `macroRuntime`.
+ * Can be overridden by analyzer plugins (see AnalyzerPlugins.pluginsMacroRuntime for more details)
+ */
private val macroRuntimesCache = perRunCaches.newWeakMap[Symbol, MacroRuntime]
- def macroRuntime(expandee: Tree): MacroRuntime = {
+ def standardMacroRuntime(expandee: Tree): MacroRuntime = {
val macroDef = expandee.symbol
macroLogVerbose(s"looking for macro implementation: $macroDef")
if (fastTrack contains macroDef) {
View
2  src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
@@ -40,7 +40,7 @@ trait Analyzer extends AnyRef
override def keepsTypeParams = false
def apply(unit: CompilationUnit) {
- pluginsEnterSym(newNamer(rootContext(unit)), unit.body)
+ newNamer(rootContext(unit)).enterSym(unit.body)
}
}
}
View
50 src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala
@@ -180,7 +180,7 @@ trait AnalyzerPlugins { self: Analyzer =>
* Typechecks the right-hand side of a macro definition (which typically features
* a mere reference to a macro implementation).
*
- * Default implementation provided in `self.typedMacroBody` makes sure that the rhs
+ * Default implementation provided in `self.standardTypedMacroBody` makes sure that the rhs
* resolves to a reference to a method in either a static object or a macro bundle,
* verifies that the referred method is compatible with the macro def and upon success
* attaches a macro impl binding to the macro def's symbol.
@@ -193,7 +193,7 @@ trait AnalyzerPlugins { self: Analyzer =>
* Expands an application of a def macro (i.e. of a symbol that has the MACRO flag set),
* possibly using the current typer mode and the provided prototype.
*
- * Default implementation provided in `self.macroExpand` figures out whether the `expandee`
+ * Default implementation provided in `self.standardMacroExpand` figures out whether the `expandee`
* needs to be expanded right away or its expansion has to be delayed until all undetermined
* parameters are inferred, then loads the macro implementation using `self.pluginsMacroRuntime`,
* prepares the invocation arguments for the macro implementation using `self.pluginsMacroArgs`,
@@ -211,7 +211,7 @@ trait AnalyzerPlugins { self: Analyzer =>
/**
* Computes the arguments that need to be passed to the macro impl corresponding to a particular expandee.
*
- * Default implementation provided in `self.macroArgs` instantiates a `scala.reflect.macros.contexts.Context`,
+ * Default implementation provided in `self.standardMacroArgs` instantiates a `scala.reflect.macros.contexts.Context`,
* gathers type and value arguments of the macro application and throws them together into `MacroArgs`.
*
* $nonCumulativeReturnValueDoc.
@@ -221,7 +221,7 @@ trait AnalyzerPlugins { self: Analyzer =>
/**
* Summons a function that encapsulates macro implementation invocations for a particular expandee.
*
- * Default implementation provided in `self.macroRuntime` returns a function that
+ * Default implementation provided in `self.standardMacroRuntime` returns a function that
* loads the macro implementation binding from the macro definition symbol,
* then uses either Java or Scala reflection to acquire the method that corresponds to the impl,
* and then reflectively calls into that method.
@@ -233,7 +233,7 @@ trait AnalyzerPlugins { self: Analyzer =>
/**
* Creates a symbol for the given tree in lexical context encapsulated by the given namer.
*
- * Default implementation provided in `namer.enterSym` handles MemberDef's and Imports,
+ * Default implementation provided in `namer.standardEnterSym` handles MemberDef's and Imports,
* doing nothing for other trees (DocDef's are seen through and rewrapped). Typical implementation
* of `enterSym` for a particular tree flavor creates a corresponding symbol, assigns it to the tree,
* enters the symbol into scope and then might even perform some code generation.
@@ -245,7 +245,7 @@ trait AnalyzerPlugins { self: Analyzer =>
/**
* Makes sure that for the given class definition, there exists a companion object definition.
*
- * Default implementation provided in `namer.ensureCompanionObject` looks up a companion symbol for the class definition
+ * Default implementation provided in `namer.standardEnsureCompanionObject` looks up a companion symbol for the class definition
* and then checks whether the resulting symbol exists or not. If it exists, then nothing else is done.
* If not, a synthetic object definition is created using the provided factory, which is then entered into namer's scope.
*
@@ -371,7 +371,7 @@ trait AnalyzerPlugins { self: Analyzer =>
def pluginsTypedMacroBody(typer: Typer, ddef: DefDef): Tree = invoke(new NonCumulativeOp[Tree] {
def position = ddef.pos
def description = "typecheck this macro definition"
- def default = typedMacroBody(typer, ddef)
+ def default = standardTypedMacroBody(typer, ddef)
def custom(plugin: MacroPlugin) = plugin.pluginsTypedMacroBody(typer, ddef)
})
@@ -379,7 +379,7 @@ trait AnalyzerPlugins { self: Analyzer =>
def pluginsMacroExpand(typer: Typer, expandee: Tree, mode: Mode, pt: Type): Tree = invoke(new NonCumulativeOp[Tree] {
def position = expandee.pos
def description = "expand this macro application"
- def default = macroExpand(typer, expandee, mode, pt)
+ def default = standardMacroExpand(typer, expandee, mode, pt)
def custom(plugin: MacroPlugin) = plugin.pluginsMacroExpand(typer, expandee, mode, pt)
})
@@ -387,7 +387,7 @@ trait AnalyzerPlugins { self: Analyzer =>
def pluginsMacroArgs(typer: Typer, expandee: Tree): MacroArgs = invoke(new NonCumulativeOp[MacroArgs] {
def position = expandee.pos
def description = "compute macro arguments for this macro application"
- def default = macroArgs(typer, expandee)
+ def default = standardMacroArgs(typer, expandee)
def custom(plugin: MacroPlugin) = plugin.pluginsMacroArgs(typer, expandee)
})
@@ -395,30 +395,32 @@ trait AnalyzerPlugins { self: Analyzer =>
def pluginsMacroRuntime(expandee: Tree): MacroRuntime = invoke(new NonCumulativeOp[MacroRuntime] {
def position = expandee.pos
def description = "compute macro runtime for this macro application"
- def default = macroRuntime(expandee)
+ def default = standardMacroRuntime(expandee)
def custom(plugin: MacroPlugin) = plugin.pluginsMacroRuntime(expandee)
})
/** @see MacroPlugin.pluginsEnterSym */
- def pluginsEnterSym(namer: Namer, tree: Tree): Context = invoke(new NonCumulativeOp[Context] {
- def position = tree.pos
- def description = "enter a symbol for this tree"
- def default = namer.enterSym(tree)
- def custom(plugin: MacroPlugin) = {
- val hasExistingSym = tree.symbol != NoSymbol
- val result = plugin.pluginsEnterSym(namer, tree)
- if (result && hasExistingSym) Some(namer.context)
- else if (result && tree.isInstanceOf[Import]) Some(namer.context.make(tree))
- else if (result) Some(namer.context)
- else None
- }
- })
+ def pluginsEnterSym(namer: Namer, tree: Tree): Context =
+ if (macroPlugins.isEmpty) namer.standardEnterSym(tree)
+ else invoke(new NonCumulativeOp[Context] {
+ def position = tree.pos
+ def description = "enter a symbol for this tree"
+ def default = namer.standardEnterSym(tree)
+ def custom(plugin: MacroPlugin) = {
+ val hasExistingSym = tree.symbol != NoSymbol
+ val result = plugin.pluginsEnterSym(namer, tree)
+ if (result && hasExistingSym) Some(namer.context)
+ else if (result && tree.isInstanceOf[Import]) Some(namer.context.make(tree))
+ else if (result) Some(namer.context)
+ else None
+ }
+ })
/** @see MacroPlugin.pluginsEnsureCompanionObject */
def pluginsEnsureCompanionObject(namer: Namer, cdef: ClassDef, creator: ClassDef => Tree = companionModuleDef(_)): Symbol = invoke(new NonCumulativeOp[Symbol] {
def position = cdef.pos
def description = "enter a companion symbol for this tree"
- def default = namer.ensureCompanionObject(cdef, creator)
+ def default = namer.standardEnsureCompanionObject(cdef, creator)
def custom(plugin: MacroPlugin) = plugin.pluginsEnsureCompanionObject(namer, cdef, creator)
})
View
30 src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -314,7 +314,12 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
* @return Macro impl reference for the given macro definition if everything is okay.
* EmptyTree if an error occurs.
*/
- def typedMacroBody(typer: Typer, macroDdef: DefDef): Tree = {
+ def typedMacroBody(typer: Typer, macroDdef: DefDef): Tree = pluginsTypedMacroBody(typer, macroDdef)
+
+ /** Default implementation of `typedMacroBody`.
+ * Can be overridden by analyzer plugins (see AnalyzerPlugins.pluginsTypedMacroBody for more details)
+ */
+ def standardTypedMacroBody(typer: Typer, macroDdef: DefDef): Tree = {
val macroDef = macroDdef.symbol
assert(macroDef.isMacro, macroDdef)
@@ -359,8 +364,12 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
/** Calculate the arguments to pass to a macro implementation when expanding the provided tree.
*/
case class MacroArgs(c: MacroContext, others: List[Any])
+ def macroArgs(typer: Typer, expandee: Tree): MacroArgs = pluginsMacroArgs(typer, expandee)
- def macroArgs(typer: Typer, expandee: Tree): MacroArgs = {
+ /** Default implementation of `macroArgs`.
+ * Can be overridden by analyzer plugins (see AnalyzerPlugins.pluginsMacroArgs for more details)
+ */
+ def standardMacroArgs(typer: Typer, expandee: Tree): MacroArgs = {
val macroDef = expandee.symbol
val paramss = macroDef.paramss
val treeInfo.Applied(core, targs, argss) = expandee
@@ -561,7 +570,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
onFailure(typer.infer.setError(expandee))
} else try {
val expanded = {
- val runtime = pluginsMacroRuntime(expandee)
+ val runtime = macroRuntime(expandee)
if (runtime != null) macroExpandWithRuntime(typer, expandee, runtime)
else macroExpandWithoutRuntime(typer, expandee)
}
@@ -688,7 +697,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
else {
forced += delayed
typer.infer.inferExprInstance(delayed, typer.context.extractUndetparams(), outerPt, keepNothings = false)
- pluginsMacroExpand(typer, delayed, mode, outerPt)
+ macroExpand(typer, delayed, mode, outerPt)
}
} else delayed
}
@@ -698,7 +707,12 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
/** Expands a term macro used in apply role as `M(2)(3)` in `val x = M(2)(3)`.
* @see DefMacroExpander
*/
- def macroExpand(typer: Typer, expandee: Tree, mode: Mode, pt: Type): Tree = {
+ def macroExpand(typer: Typer, expandee: Tree, mode: Mode, pt: Type): Tree = pluginsMacroExpand(typer, expandee, mode, pt)
+
+ /** Default implementation of `macroExpand`.
+ * Can be overridden by analyzer plugins (see AnalyzerPlugins.pluginsMacroExpand for more details)
+ */
+ def standardMacroExpand(typer: Typer, expandee: Tree, mode: Mode, pt: Type): Tree = {
val expander = new DefMacroExpander(typer, expandee, mode, pt)
expander(expandee)
}
@@ -730,12 +744,12 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
case (false, true) =>
macroLogLite("macro expansion is delayed: %s".format(expandee))
delayed += expandee -> undetparams
- expandee updateAttachment MacroRuntimeAttachment(delayed = true, typerContext = typer.context, macroContext = Some(pluginsMacroArgs(typer, expandee).c))
+ expandee updateAttachment MacroRuntimeAttachment(delayed = true, typerContext = typer.context, macroContext = Some(macroArgs(typer, expandee).c))
Delay(expandee)
case (false, false) =>
import typer.TyperErrorGen._
macroLogLite("performing macro expansion %s at %s".format(expandee, expandee.pos))
- val args = pluginsMacroArgs(typer, expandee)
+ val args = macroArgs(typer, expandee)
try {
val numErrors = reporter.ERROR.count
def hasNewErrors = reporter.ERROR.count > numErrors
@@ -850,7 +864,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
context.implicitsEnabled = typer.context.implicitsEnabled
context.enrichmentEnabled = typer.context.enrichmentEnabled
context.macrosEnabled = typer.context.macrosEnabled
- pluginsMacroExpand(newTyper(context), tree, EXPRmode, WildcardType)
+ macroExpand(newTyper(context), tree, EXPRmode, WildcardType)
case _ =>
tree
})
View
27 src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -243,7 +243,12 @@ trait Namers extends MethodSynthesis {
validate(sym2.companionClass)
}
- def enterSym(tree: Tree): Context = {
+ def enterSym(tree: Tree): Context = pluginsEnterSym(this, tree)
+
+ /** Default implementation of `enterSym`.
+ * Can be overridden by analyzer plugins (see AnalyzerPlugins.pluginsEnterSym for more details)
+ */
+ def standardEnterSym(tree: Tree): Context = {
def dispatch() = {
var returnContext = this.context
tree match {
@@ -253,7 +258,7 @@ trait Namers extends MethodSynthesis {
case tree @ ValDef(_, _, _, _) => enterValDef(tree)
case tree @ DefDef(_, _, _, _, _, _) => enterDefDef(tree)
case tree @ TypeDef(_, _, _, _) => enterTypeDef(tree)
- case DocDef(_, defn) => pluginsEnterSym(this, defn)
+ case DocDef(_, defn) => enterSym(defn)
case tree @ Import(_, _) =>
assignSymbol(tree)
returnContext = context.make(tree)
@@ -452,7 +457,7 @@ trait Namers extends MethodSynthesis {
def enterSyms(trees: List[Tree]): Namer = {
trees.foldLeft(this: Namer) { (namer, t) =>
- val ctx = pluginsEnterSym(namer, t)
+ val ctx = namer enterSym t
// for Import trees, enterSym returns a changed context, so we need a new namer
if (ctx eq namer.context) namer
else newNamer(ctx)
@@ -466,7 +471,13 @@ trait Namers extends MethodSynthesis {
* class definition tree.
* @return the companion object symbol.
*/
- def ensureCompanionObject(cdef: ClassDef, creator: ClassDef => Tree = companionModuleDef(_)): Symbol = {
+ def ensureCompanionObject(cdef: ClassDef, creator: ClassDef => Tree = companionModuleDef(_)): Symbol =
+ pluginsEnsureCompanionObject(this, cdef, creator)
+
+ /** Default implementation of `ensureCompanionObject`.
+ * Can be overridden by analyzer plugins (see AnalyzerPlugins.pluginsEnsureCompanionObject for more details)
+ */
+ def standardEnsureCompanionObject(cdef: ClassDef, creator: ClassDef => Tree = companionModuleDef(_)): Symbol = {
val m = companionSymbolOf(cdef.symbol, context)
// @luc: not sure why "currentRun.compiles(m)" is needed, things breaks
// otherwise. documentation welcome.
@@ -662,7 +673,7 @@ trait Namers extends MethodSynthesis {
tree.symbol setInfo completerOf(tree)
if (mods.isCase) {
- val m = pluginsEnsureCompanionObject(this, tree, caseModuleDef)
+ val m = ensureCompanionObject(tree, caseModuleDef)
m.moduleClass.updateAttachment(new ClassForCaseCompanionAttachment(tree))
}
val hasDefault = impl.body exists {
@@ -670,7 +681,7 @@ trait Namers extends MethodSynthesis {
case _ => false
}
if (hasDefault) {
- val m = pluginsEnsureCompanionObject(this, tree)
+ val m = ensureCompanionObject(tree)
m.updateAttachment(new ConstructorDefaultsAttachment(tree, null))
}
val owner = tree.symbol.owner
@@ -697,7 +708,7 @@ trait Namers extends MethodSynthesis {
def enterIfNotThere(sym: Symbol) { }
def enterSyntheticSym(tree: Tree): Symbol = {
- pluginsEnterSym(this, tree)
+ enterSym(tree)
context.unit.synthetics(tree.symbol) = tree
tree.symbol
}
@@ -931,7 +942,7 @@ trait Namers extends MethodSynthesis {
log("Ensuring companion for derived value class " + cdef.name + " at " + cdef.pos.show)
clazz setFlag FINAL
// Don't force the owner's info lest we create cycles as in SI-6357.
- pluginsEnsureCompanionObject(enclosingNamerWithScope(clazz.owner.rawInfo.decls), cdef)
+ enclosingNamerWithScope(clazz.owner.rawInfo.decls).ensureCompanionObject(cdef)
}
pluginsTp
}
View
12 src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1112,7 +1112,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
if (tree.isType)
adaptType()
else if (mode.typingExprNotFun && treeInfo.isMacroApplication(tree) && !isMacroExpansionSuppressed(tree))
- pluginsMacroExpand(this, tree, mode, pt)
+ macroExpand(this, tree, mode, pt)
else if (mode.typingConstructorPattern)
typedConstructorPattern(tree, pt)
else if (shouldInsertApply(tree))
@@ -1863,8 +1863,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
protected def enterSym(txt: Context, tree: Tree): Context =
- if (txt eq context) pluginsEnterSym(namer, tree)
- else pluginsEnterSym(newNamer(txt), tree)
+ if (txt eq context) namer enterSym tree
+ else newNamer(txt) enterSym tree
/** <!-- 2 --> Check that inner classes do not inherit from Annotation
*/
@@ -2213,7 +2213,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
} else if (meth.isMacro) {
// typechecking macro bodies is sort of unconventional
// that's why we employ our custom typing scheme orchestrated outside of the typer
- transformedOr(ddef.rhs, pluginsTypedMacroBody(this, ddef))
+ transformedOr(ddef.rhs, typedMacroBody(this, ddef))
} else {
transformedOrTyped(ddef.rhs, EXPRmode, tpt1.tpe)
}
@@ -3812,7 +3812,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
protected def typedExistentialTypeTree(tree: ExistentialTypeTree, mode: Mode): Tree = {
for (wc <- tree.whereClauses)
- if (wc.symbol == NoSymbol) { pluginsEnterSym(namer, wc); wc.symbol setFlag EXISTENTIAL }
+ if (wc.symbol == NoSymbol) { namer enterSym wc; wc.symbol setFlag EXISTENTIAL }
else context.scope enter wc.symbol
val whereClauses1 = typedStats(tree.whereClauses, context.owner)
for (vd @ ValDef(_, _, _, _) <- whereClauses1)
@@ -5517,7 +5517,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// here we guard against this case
transformed(ddef.rhs)
} else {
- val rhs1 = pluginsTypedMacroBody(this, ddef)
+ val rhs1 = typedMacroBody(this, ddef)
transformed(ddef.rhs) = rhs1
rhs1
}
View
2  src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala
@@ -52,7 +52,7 @@ trait ReplGlobal extends Global {
def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) {
def apply(unit: CompilationUnit) {
repldbg("Running replPhase on " + unit.body)
- // pluginsEnterSym(newNamer(rootContext(unit)), unit.body)
+ // newNamer(rootContext(unit)).enterSym(unit.body)
}
}
}
View
2  test/files/neg/macro-incompatible-macro-engine/Plugin_1.scala
@@ -25,7 +25,7 @@ class Plugin(val global: Global) extends NscPlugin {
}.transform(tree)
override def pluginsTypedMacroBody(typer: Typer, ddef: DefDef): Option[Tree] = {
- val result = typedMacroBody(typer, ddef)
+ val result = standardTypedMacroBody(typer, ddef)
val List(AnnotationInfo(atp, List(Apply(nucleus, _ :: others)), Nil)) = ddef.symbol.annotations
val updatedBinding = Apply(nucleus, Assign(Literal(Constant("macroEngine")), Literal(Constant("vxxx (implemented in the incompatibleMacroEngine plugin)"))) :: others)
ddef.symbol.setAnnotations(List(AnnotationInfo(atp, List(fixupBinding(updatedBinding)), Nil)))
View
2  test/files/run/macroPlugins-macroArgs/Plugin_1.scala
@@ -14,7 +14,7 @@ class Plugin(val global: Global) extends NscPlugin {
object MacroPlugin extends MacroPlugin {
override def pluginsMacroArgs(typer: Typer, expandee: Tree): Option[MacroArgs] = {
- val MacroArgs(c, List(Literal(Constant(s: String)))) = macroArgs(typer, expandee)
+ val MacroArgs(c, List(Literal(Constant(s: String)))) = standardMacroArgs(typer, expandee)
Some(MacroArgs(c, List(Literal(Constant("hijacked " + s)))))
}
}
View
4 test/files/run/macroPlugins-namerHooks.scala
@@ -18,12 +18,12 @@ object Test extends DirectTest {
object macroPlugin extends MacroPlugin {
override def pluginsEnterSym(namer: Namer, tree: Tree): Boolean = {
output += s"enterSym(${tree.toString.replace('\n', ' ')})"
- namer.enterSym(tree)
+ namer.standardEnterSym(tree)
true
}
override def pluginsEnsureCompanionObject(namer: Namer, cdef: ClassDef, creator: ClassDef => Tree = companionModuleDef(_)): Option[Symbol] = {
output += s"ensureCompanionObject(${cdef.toString.replace('\n', ' ')}, ...)"
- Some(namer.ensureCompanionObject(cdef, creator))
+ Some(namer.standardEnsureCompanionObject(cdef, creator))
}
override def pluginsEnterStats(typer: Typer, stats: List[Tree]): List[Tree] = {
stats.foreach(stat => output += s"enterStat(${stat.toString.replace('\n', ' ')})")
View
2  test/files/run/macroPlugins-typedMacroBody/Plugin_1.scala
@@ -15,7 +15,7 @@ class Plugin(val global: Global) extends NscPlugin {
object MacroPlugin extends MacroPlugin {
override def pluginsTypedMacroBody(typer: Typer, ddef: DefDef): Option[Tree] = {
val DefDef(_, _, _, _, _, Literal(Constant(num: Int))) = ddef
- Some(typedMacroBody(typer, copyDefDef(ddef)(rhs = Ident(TermName("impl" + num)))))
+ Some(standardTypedMacroBody(typer, copyDefDef(ddef)(rhs = Ident(TermName("impl" + num)))))
}
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.