Skip to content

Commit 39ea6fb

Browse files
committed
Set Macro flag and containsQuotesOrSplices in PostTyper
It's easier to handle this in PostTyper since then we do not need to distinguish between inlined and normal code. Also, need to record quotes as well as splices since ReifyQuotes should also do macro expansion. Also, add a missing recursive call to `transform` in ReifyQuotes.
1 parent 33a93a6 commit 39ea6fb

File tree

5 files changed

+27
-17
lines changed

5 files changed

+27
-17
lines changed

compiler/src/dotty/tools/dotc/CompilationUnit.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class CompilationUnit(val source: SourceFile) {
2525
/** Will be reset to `true` if `untpdTree` contains `Quote` trees. The information
2626
* is used in phase ReifyQuotes in order to avoid traversing a quote-less tree.
2727
*/
28-
var containsQuotes: Boolean = false
28+
var containsQuotesOrSplices: Boolean = false
2929
}
3030

3131
object CompilationUnit {

compiler/src/dotty/tools/dotc/transform/PostTyper.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,24 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
159159
}
160160
}
161161

162+
/** 1. If we are an an inline method but not in a nested quote, mark the inline method
163+
* as a macro.
164+
*
165+
* 2. If selection is a quote or splice node, record that fact in the current compilation unit.
166+
*/
167+
private def handleMeta(sym: Symbol)(implicit ctx: Context): Unit = {
168+
169+
def markAsMacro(c: Context): Unit =
170+
if (c.owner eq c.outer.owner) markAsMacro(c.outer)
171+
else if (c.owner.isInlineMethod) c.owner.setFlag(Macro)
172+
else if (!c.outer.owner.is(Package)) markAsMacro(c.outer)
173+
174+
if (sym.isSplice || sym.isQuote) {
175+
markAsMacro(ctx)
176+
ctx.compilationUnit.containsQuotesOrSplices = true
177+
}
178+
}
179+
162180
override def transform(tree: Tree)(implicit ctx: Context): Tree =
163181
try tree match {
164182
case tree: Ident if !tree.isType =>
@@ -167,6 +185,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
167185
case _ => tree
168186
}
169187
case tree @ Select(qual, name) =>
188+
handleMeta(tree.symbol)
170189
if (name.isTypeName) {
171190
Checking.checkRealizable(qual.tpe, qual.pos.focus)
172191
super.transform(tree)

compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class ReifyQuotes extends MacroTransform {
2424
override def phaseName: String = "reifyQuotes"
2525

2626
override def run(implicit ctx: Context): Unit =
27-
if (ctx.compilationUnit.containsQuotes) super.run
27+
if (ctx.compilationUnit.containsQuotesOrSplices) super.run
2828

2929
protected def newTransformer(implicit ctx: Context): Transformer =
3030
new Reifier(inQuote = false, null, 0, new LevelInfo)
@@ -336,7 +336,7 @@ class ReifyQuotes extends MacroTransform {
336336
case Inlined(call, bindings, expansion @ Select(body, name)) if expansion.symbol.isSplice =>
337337
// To maintain phase consistency, convert inlined expressions of the form
338338
// `{ bindings; ~expansion }` to `~{ bindings; expansion }`
339-
cpy.Select(expansion)(cpy.Inlined(tree)(call, bindings, body), name)
339+
transform(cpy.Select(expansion)(cpy.Inlined(tree)(call, bindings, body), name))
340340
case _: Import =>
341341
tree
342342
case tree: DefDef if tree.symbol.is(Macro) && level == 0 =>

compiler/src/dotty/tools/dotc/transform/SymUtils.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ class SymUtils(val self: Symbol) extends AnyVal {
176176
else owner.isLocal
177177
}
178178

179+
/** Is symbol a quote operation? */
180+
def isQuote(implicit ctx: Context): Boolean =
181+
self == defn.quoteMethod || self == defn.typeQuoteMethod
182+
179183
/** Is symbol a splice operation? */
180184
def isSplice(implicit ctx: Context): Boolean =
181185
self == defn.QuotedExpr_~ || self == defn.QuotedType_~

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -394,23 +394,11 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
394394

395395
def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = track("typedSelect") {
396396

397-
/** If we are an an inline method but not in a nested quote, mark the inline method
398-
* as a macro.
399-
*/
400-
def markAsMacro(c: Context): Unit =
401-
if (!c.tree.isInstanceOf[untpd.Quote])
402-
if (c.owner eq c.outer.owner) markAsMacro(c.outer)
403-
else if (c.owner.isInlineMethod) c.owner.setFlag(Macro)
404-
else if (!c.outer.owner.is(Package)) markAsMacro(c.outer)
405-
406397
def typeSelectOnTerm(implicit ctx: Context): Tree = {
407398
val qual1 = typedExpr(tree.qualifier, selectionProto(tree.name, pt, this))
408399
if (tree.name.isTypeName) checkStable(qual1.tpe, qual1.pos)
409400
val select = typedSelect(tree, pt, qual1)
410-
if (select.tpe ne TryDynamicCallType) {
411-
if (select.symbol.isSplice) markAsMacro(ctx)
412-
select
413-
}
401+
if (select.tpe ne TryDynamicCallType) select
414402
else if (pt.isInstanceOf[PolyProto] || pt.isInstanceOf[FunProto] || pt == AssignProto) select
415403
else typedDynamicSelect(tree, Nil, pt)
416404
}
@@ -1086,7 +1074,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
10861074
}
10871075

10881076
def typedQuote(tree: untpd.Quote, pt: Type)(implicit ctx: Context): Tree = track("typedQuote") {
1089-
ctx.compilationUnit.containsQuotes = true
10901077
val untpd.Quote(body) = tree
10911078
val isType = body.isType
10921079
val resultClass = if (isType) defn.QuotedTypeClass else defn.QuotedExprClass

0 commit comments

Comments
 (0)