Skip to content

Instantly share code, notes, and snippets.

@adriaanm
Created May 8, 2018 13:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adriaanm/bdaec0588ad6fdf3bbe6ea09d31edf87 to your computer and use it in GitHub Desktop.
Save adriaanm/bdaec0588ad6fdf3bbe6ea09d31edf87 to your computer and use it in GitHub Desktop.
macro paradise namers/expanders diff
--- /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