Created
May 8, 2018 13:54
-
-
Save adriaanm/bdaec0588ad6fdf3bbe6ea09d31edf87 to your computer and use it in GitHub Desktop.
macro paradise namers/expanders diff
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- /tmp/para-namers.scala 2018-05-08 15:52:02.000000000 +0200 | |
+++ src/compiler/scala/tools/nsc/typechecker/MacroAnnotationNamers.scala 2018-05-08 15:52:32.000000000 +0200 | |
@@ -1,28 +1,22 @@ | |
-package org.scalamacros.paradise | |
-package typechecker | |
- | |
-trait Namers { | |
- self: AnalyzerPlugins => | |
+package scala.tools.nsc.typechecker | |
+// imported from scalamacros/paradise | |
+trait MacroAnnotationNamers { self: Analyzer => | |
import global._ | |
import analyzer._ | |
import definitions._ | |
import scala.reflect.internal.Flags._ | |
- import analyzer.{Namer => NscNamer} | |
+ import scala.reflect.internal.Mode._ | |
- def mkNamer(namer0: NscNamer) = new { val namer: NscNamer = namer0 } with Namer with Expander | |
- trait Namer { | |
- self: Namer with Expander => | |
- | |
- val namer: NscNamer | |
- import namer._ | |
- val namerErrorGen = new ErrorGen(namer.typer) | |
- import namerErrorGen._ | |
+ override def newNamer(context: Context): Namer = new MacroAnnotationNamer(context) | |
+ | |
+ class MacroAnnotationNamer(context: Context) extends Namer(context) { | |
import NamerErrorGen._ | |
+ import typer.TyperErrorGen._ | |
- def enterSym(tree: Tree): Context = { | |
+ override def standardEnterSym(tree: Tree): Context = { | |
def dispatch() = { | |
- var returnContext = namer.context | |
+ var returnContext = context | |
tree match { | |
case DocDef(_, mdef) => | |
enterSym(mdef) | |
@@ -38,12 +32,12 @@ | |
returnContext | |
} | |
tree.symbol match { | |
- case NoSymbol => try dispatch() catch typeErrorHandler(tree, namer.context) | |
+ case NoSymbol => try dispatch() catch typeErrorHandler(tree, context) | |
case sym => enterExistingSym(sym, tree) | |
} | |
} | |
- def createAssignAndEnterSymbol(tree: Tree, mask: Long = -1L): Symbol = { | |
+ protected def createAssignAndEnterSymbol(tree: Tree, mask: Long = -1L): Symbol = { | |
def coreCreateAssignAndEnterSymbol = { | |
val sym = tree match { | |
case PackageDef(pid, _) => createPackageSymbol(tree.pos, pid) // package symbols are entered elsewhere | |
@@ -146,24 +140,24 @@ | |
} | |
// reimplemented to integrate with weakEnsureCompanionObject | |
- def ensureCompanionObject(cdef: ClassDef, creator: ClassDef => Tree = companionModuleDef(_)): Symbol = { | |
+ override def standardEnsureCompanionObject(cdef: ClassDef, creator: ClassDef => Tree = companionModuleDef(_)): Symbol = { | |
val m = patchedCompanionSymbolOf(cdef.symbol, context) | |
- def synthesizeTree = atPos(cdef.pos.focus)(creator(cdef)) | |
+ | |
if (m != NoSymbol && currentRun.compiles(m) && !isWeak(m)) m | |
- else unmarkWeak(enterSyntheticSym(synthesizeTree)) | |
+ else unmarkWeak(enterSyntheticSym(atPos(cdef.pos.focus)(creator(cdef)))) | |
} | |
/** Does the same as `ensureCompanionObject`, but also makes sure that the returned symbol destroys itself | |
* if noone ends up using it (either by calling `ensureCompanionObject` or by `finishSymbol`). | |
*/ | |
// TODO: deduplicate | |
- def weakEnsureCompanionObject(cdef: ClassDef, creator: ClassDef => Tree = companionModuleDef(_)): Symbol = { | |
+ protected def weakEnsureCompanionObject(cdef: ClassDef, creator: ClassDef => Tree = companionModuleDef(_)): Symbol = { | |
val m = patchedCompanionSymbolOf(cdef.symbol, context) | |
if (m != NoSymbol && currentRun.compiles(m)) m | |
else { val mdef = atPos(cdef.pos.focus)(creator(cdef)); enterSym(mdef); markWeak(mdef.symbol) } | |
} | |
- def finishSymbol(tree: Tree) { | |
+ protected def finishSymbol(tree: Tree): Unit = { | |
// annotations on parameters expand together with their owners | |
// therefore when we actually get to enter the parameters, we shouldn't even bother checking | |
// TODO: we don't handle primary ctors that might get spuriously marked as maybe expandees because of primary paramss | |
@@ -208,7 +202,7 @@ | |
} | |
} | |
- def finishSymbolNotExpandee(tree: Tree) { | |
+ protected def finishSymbolNotExpandee(tree: Tree): Unit = { | |
val sym = tree.symbol | |
def savingLock[T](op: => T): T = { | |
val wasLocked = sym.hasFlag(LOCKED) | |
@@ -216,11 +210,16 @@ | |
if (wasLocked) sym.setFlag(LOCKED) | |
result | |
} | |
- savingLock(tree match { | |
+ | |
+ savingLock { | |
+ tree match { | |
case tree @ PackageDef(_, _) => | |
newNamer(context.make(tree, sym.moduleClass, sym.info.decls)) enterSyms tree.stats | |
case tree @ ClassDef(mods, name, tparams, impl) => | |
- sym setInfo completerOf(tree) | |
+ val primaryConstructorArity = treeInfo.firstConstructorArgs(impl.body).size | |
+ // not entering | |
+ tree.symbol setInfo completerOf(tree) | |
+ | |
if (mods.isCase) { | |
val m = ensureCompanionObject(tree, caseModuleDef) | |
m.moduleClass.updateAttachment(new ClassForCaseCompanionAttachment(tree)) | |
@@ -239,11 +238,11 @@ | |
} | |
// Suggested location only. | |
if (mods.isImplicit) { | |
- if (treeInfo.primaryConstructorArity(tree) == 1) { | |
+ if (primaryConstructorArity == 1) { | |
log("enter implicit wrapper "+tree+", owner = "+owner) | |
enterImplicitWrapper(tree) | |
} | |
- else MultipleParametersImplicitClassError(tree) | |
+ else reporter.error(tree.pos, "implicit classes must accept exactly one primary constructor parameter") | |
} | |
validateCompanionDefs(tree) | |
case tree @ ModuleDef(_, _, _) => | |
@@ -286,7 +285,8 @@ | |
sym setInfo completerOf(tree) | |
case tree @ Import(_, _) => | |
namerOf(tree.symbol) importTypeCompleter tree | |
- }) | |
+ } | |
+ } | |
} | |
// we have several occasions when so called "maybe expandees" need special care | |
@@ -344,14 +344,14 @@ | |
abstract class MaybeExpandeeCompanionCompleter(tree: Tree) extends MaybeExpandeeCompleter(tree) | |
- implicit class RichType(tpe: Type) { | |
+ private implicit class RichType(tpe: Type) { | |
def completeOnlyExpansions(sym: Symbol) = tpe match { | |
- case mec: Namer#MaybeExpandeeCompleter => mec.complete(sym, onlyExpansions = true) | |
+ case mec: MacroAnnotationNamer#MaybeExpandeeCompleter => mec.complete(sym, onlyExpansions = true) | |
case c => () | |
} | |
} | |
- def finishSymbolMaybeExpandee(tree: Tree, annZippers: List[AnnotationZipper]) { | |
+ protected def finishSymbolMaybeExpandee(tree: Tree, annZippers: List[treeInfo.AnnotationZipper]) { | |
val sym = tree.symbol | |
unmarkWeak(sym) | |
markMaybeExpandee(sym) | |
@@ -360,10 +360,11 @@ | |
override def maybeExpand(): Unit = { | |
val companion = if (tree.isInstanceOf[ClassDef]) patchedCompanionSymbolOf(sym, context) else NoSymbol | |
- def maybeExpand(annotation: Tree, annottee: Tree, maybeExpandee: Tree): Option[List[Tree]] = { | |
+ def maybeExpand(annotation: Tree, annottee: Tree, maybeExpandee: Tree): Option[List[Tree]] = | |
+ if (context.macrosEnabled) { // TODO: when is this bit flipped -- can we pull this check out farther? | |
val treeInfo.Applied(Select(New(tpt), nme.CONSTRUCTOR), _, _) = annotation | |
val mann = probeMacroAnnotation(context, tpt) | |
- if (mann.isMacroAnnotation && context.macrosEnabled) { | |
+ if (mann.isClass && mann.hasFlag(MACRO)) { | |
assert(!currentRun.compiles(mann), mann) | |
val annm = prepareAnnotationMacro(annotation, mann, sym, annottee, maybeExpandee) | |
expandAnnotationMacro(tree, annm) | |
@@ -373,14 +374,16 @@ | |
// but when manning we aren't in typer, so we don't have to do as macroExpand1 does | |
// and also there's a good reason not to ban other macro annotations | |
// if we do ban them, we might get spurious compilation errors from non-existent members that could've been generated | |
- } else { | |
- None | |
- } | |
- } | |
+ } else None | |
+ } else None | |
- annZippers.toStream.flatMap(annz => maybeExpand(annz.annotation, annz.annottee, annz.owner)).headOption match { | |
+ annZippers.iterator.flatMap(annz => maybeExpand(annz.annotation, annz.annottee, annz.owner)).nextOption match { | |
case Some(expanded) => | |
- tellReplAboutExpansion(sym, companion, expanded) | |
+ // TODO: The workaround employed in https://github.com/scalamacros/paradise/issues/19 | |
+ // no longer works because of the REPL refactoring in 2.13.0-M2. | |
+ // See https://github.com/scalamacros/paradise/issues/102 for discussion. | |
+ //tellReplAboutExpansion(sym, companion, expanded) | |
+ | |
markExpanded(sym) | |
markExpanded(companion) | |
// expansion brings new trees, probably wildly different from current ones. what do we do? | |
@@ -411,8 +414,8 @@ | |
// * non-FSMEC completer for the module and then FSMEC => fallback should call native completer | |
// * FSMEC from enterSyntheticSym for a phantom module and then FSMEC again => fallback should do nothing | |
// now it's easy to see that both are correctly handled here | |
- def finishSymbolMaybeExpandeeCompanion(tree: Tree, m: Symbol, c: Symbol) { | |
- val worthBackingUp = !m.rawInfo.isInstanceOf[Namer#MaybeExpandeeCompanionCompleter] | |
+ protected def finishSymbolMaybeExpandeeCompanion(tree: Tree, m: Symbol, c: Symbol) { | |
+ val worthBackingUp = !m.rawInfo.isInstanceOf[MacroAnnotationNamer#MaybeExpandeeCompanionCompleter] | |
if (worthBackingUp) backupCompleter(m) | |
markMaybeExpandee(m) | |
m.setInfo(new MaybeExpandeeCompanionCompleter(tree) { | |
@@ -438,7 +441,7 @@ | |
val aliveAndKicking = !destroyedDuringExpansion && !failedToMaterializeDuringExpansion | |
if (aliveAndKicking && isNotExpandable(c)) { | |
if (worthBackingUp) restoreCompleter(m) | |
- val maybeExpandee = m.rawInfo.isInstanceOf[Namer#MaybeExpandeeCompleter] | |
+ val maybeExpandee = m.rawInfo.isInstanceOf[MacroAnnotationNamer#MaybeExpandeeCompleter] | |
if (maybeExpandee) markMaybeExpandee(m) else markNotExpandable(m) | |
} | |
} | |
@@ -449,7 +452,7 @@ | |
// adaptations = ignore error reporting + ignore java + don't force symbols being compiled | |
// the last requirement leads to us being imprecise in some situation wrt normal name resolution | |
// but that's okay, since it's the only way for manns to remain modular and not to cripple normal annotations | |
- def probeMacroAnnotation(context: Context, tpt: Tree): Symbol = { | |
+ protected def probeMacroAnnotation(context: Context, tpt: Tree): Symbol = { | |
// SAFE HELPERS (can't cause unnecessary completions) | |
def reallyExists(sym: Symbol) = { if (newTyper(context).isStale(sym)) sym.setInfo(NoType); exists(sym) } | |
def qualifies(sym: Symbol): Boolean = sym.hasRawInfo && reallyExists(sym) | |
@@ -582,7 +585,7 @@ | |
// see https://github.com/scalamacros/paradise/issues/7 | |
// also see https://github.com/scalamacros/paradise/issues/64 | |
- def patchedCompanionSymbolOf(original: Symbol, ctx: Context): Symbol = if (original == NoSymbol) NoSymbol else { | |
+ protected def patchedCompanionSymbolOf(original: Symbol, ctx: Context): Symbol = if (original == NoSymbol) NoSymbol else { | |
val owner = original.owner | |
// SI-7264 Force the info of owners from previous compilation runs. | |
// Doing this generally would trigger cycles; that's what we also | |
@@ -628,31 +631,8 @@ | |
) | |
} | |
} | |
- } | |
-} | |
-package org.scalamacros.paradise | |
-package typechecker | |
- | |
-trait Expanders { | |
- self: AnalyzerPlugins => | |
- | |
- import global._ | |
- import analyzer._ | |
- import definitions._ | |
- import scala.reflect.internal.Flags._ | |
- import scala.reflect.internal.Mode._ | |
- import analyzer.{Namer => NscNamer} | |
- | |
- def mkExpander(namer0: NscNamer) = new { val namer: NscNamer = namer0 } with Namer with Expander | |
- trait Expander { | |
- self: Namer with Expander => | |
- | |
- val namer: NscNamer | |
- import namer._ | |
- val expanderErrorGen = new ErrorGen(namer.typer) | |
- import expanderErrorGen._ | |
- def prepareAnnotationMacro(ann: Tree, mann: Symbol, sym: Symbol, annottee: Tree, expandee: Tree): Tree = { | |
+ protected def prepareAnnotationMacro(ann: Tree, mann: Symbol, sym: Symbol, annottee: Tree, expandee: Tree): Tree = { | |
val companion = if (expandee.isInstanceOf[ClassDef]) patchedCompanionSymbolOf(sym, context) else NoSymbol | |
val companionSource = if (!isWeak(companion)) attachedSource(companion) else EmptyTree | |
val expandees = List(annottee, expandee, companionSource).distinct.filterNot(_.isEmpty) | |
@@ -661,7 +641,7 @@ | |
Apply(prefix, safeExpandees) setPos ann.pos | |
} | |
- def expandAnnotationMacro(original: Tree, expandee: Tree): Option[List[Tree]] = { | |
+ protected def expandAnnotationMacro(original: Tree, expandee: Tree): Option[List[Tree]] = { | |
val sym = original.symbol | |
val companion = if (original.isInstanceOf[ClassDef]) patchedCompanionSymbolOf(sym, context) else NoSymbol | |
val wasWeak = isWeak(companion) | |
@@ -757,7 +737,7 @@ | |
} yield validatedExpansion | |
} | |
- def expandMacroAnnotations(stats: List[Tree]): List[Tree] = { | |
+ override def expandMacroAnnotations(stats: List[Tree]): List[Tree] = { | |
def mightNeedTransform(stat: Tree): Boolean = stat match { | |
case stat: DocDef => mightNeedTransform(stat.definition) | |
case stat: MemberDef => isMaybeExpandee(stat.symbol) || hasAttachedExpansion(stat.symbol) | |
@@ -776,9 +756,9 @@ | |
assert(sym != NoSymbol, (sym, stat)) | |
if (isMaybeExpandee(sym)) { | |
def assert(what: Boolean) = Predef.assert(what, s"${sym.accurateKindString} ${sym.rawname}#${sym.id} with ${sym.rawInfo.kind}") | |
- assert(sym.rawInfo.isInstanceOf[Namer#MaybeExpandeeCompleter]) | |
+ assert(sym.rawInfo.isInstanceOf[MacroAnnotationNamer#MaybeExpandeeCompleter]) | |
sym.rawInfo.completeOnlyExpansions(sym) | |
- assert(!sym.rawInfo.isInstanceOf[Namer#MaybeExpandeeCompleter]) | |
+ assert(!sym.rawInfo.isInstanceOf[MacroAnnotationNamer#MaybeExpandeeCompleter]) | |
} | |
val derivedTrees = attachedExpansion(sym).getOrElse(List(stat)) | |
val (me, others) = derivedTrees.partition(_.symbol == sym) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment