Skip to content

Commit 36b87fd

Browse files
committed
Mark inline methods containing splices as macros
If an inline method contains a toplevel splice, mark it s a macro. Furthermore, allow for serialization of the Macro flag in Tasty.
1 parent fe81595 commit 36b87fd

File tree

7 files changed

+37
-15
lines changed

7 files changed

+37
-15
lines changed

compiler/src/dotty/tools/dotc/core/Flags.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ object Flags {
414414
/** A Scala 2.12 or higher trait */
415415
final val Scala_2_12_Trait = typeFlag(58, "<scala_2_12_trait>")
416416

417-
/** A macro (Scala 2.x only) */
417+
/** A macro */
418418
final val Macro = commonFlag(59, "<macro>")
419419

420420
/** A method that is known to have inherited default parameters */

compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,8 @@ Standard-Section: "ASTs" TopLevelStat*
181181
IMPLICIT
182182
LAZY
183183
OVERRIDE
184-
INLINE // macro
184+
INLINE // inline method
185+
MACRO // inline method containing toplevel splices
185186
STATIC // mapped to static Java member
186187
OBJECT // an object or its class
187188
TRAIT // a trait
@@ -226,7 +227,7 @@ object TastyFormat {
226227

227228
final val header = Array(0x5C, 0xA1, 0xAB, 0x1F)
228229
val MajorVersion = 2
229-
val MinorVersion = 0
230+
val MinorVersion = 1
230231

231232
/** Tags used to serialize names */
232233
class NameTags {
@@ -297,6 +298,7 @@ object TastyFormat {
297298
final val SCALA2X = 29
298299
final val DEFAULTparameterized = 30
299300
final val STABLE = 31
301+
final val MACRO = 32
300302

301303
// Cat. 2: tag Nat
302304

@@ -419,6 +421,7 @@ object TastyFormat {
419421
| LAZY
420422
| OVERRIDE
421423
| INLINE
424+
| MACRO
422425
| STATIC
423426
| OBJECT
424427
| TRAIT
@@ -472,6 +475,7 @@ object TastyFormat {
472475
case LAZY => "LAZY"
473476
case OVERRIDE => "OVERRIDE"
474477
case INLINE => "INLINE"
478+
case MACRO => "MACRO"
475479
case STATIC => "STATIC"
476480
case OBJECT => "OBJECT"
477481
case TRAIT => "TRAIT"

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,7 @@ class TreePickler(pickler: TastyPickler) {
587587
if (flags is Case) writeByte(CASE)
588588
if (flags is Override) writeByte(OVERRIDE)
589589
if (flags is Inline) writeByte(INLINE)
590+
if (flags is Macro) writeByte(MACRO)
590591
if (flags is JavaStatic) writeByte(STATIC)
591592
if (flags is Module) writeByte(OBJECT)
592593
if (flags is Local) writeByte(LOCAL)

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ class TreeUnpickler(reader: TastyReader,
524524
case LAZY => addFlag(Lazy)
525525
case OVERRIDE => addFlag(Override)
526526
case INLINE => addFlag(Inline)
527+
case MACRO => addFlag(Macro)
527528
case STATIC => addFlag(JavaStatic)
528529
case OBJECT => addFlag(Module)
529530
case TRAIT => addFlag(Trait)

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import StdNames._
1111
import ast.untpd
1212
import tasty.TreePickler.Hole
1313
import MegaPhase.MiniPhase
14+
import SymUtils._
1415
import NameKinds.OuterSelectName
1516
import scala.collection.mutable
1617

1718
// TODO
18-
// implement hole substitution directly
1919
// check that inline methods override nothing
2020
// drop inline methods
2121
// adapt to Expr/Type when passing arguments to splices
@@ -175,10 +175,6 @@ class ReifyQuotes extends MacroTransform {
175175
case _ =>
176176
}
177177

178-
/** Is symbol a splice operation? */
179-
def isSplice(sym: Symbol)(implicit ctx: Context) =
180-
sym == defn.QuotedExpr_~ || sym == defn.QuotedType_~
181-
182178
/** Are we in the body of an inline method? */
183179
def inInline(implicit ctx: Context) = ctx.owner.ownersIterator.exists(_.isInlineMethod)
184180

@@ -213,7 +209,7 @@ class ReifyQuotes extends MacroTransform {
213209
def checkType(pos: Position)(implicit ctx: Context): TypeAccumulator[Unit] = new TypeAccumulator[Unit] {
214210
def apply(acc: Unit, tp: Type): Unit = reporting.trace(i"check type level $tp at $level") {
215211
tp match {
216-
case tp: NamedType if isSplice(tp.symbol) =>
212+
case tp: NamedType if tp.symbol.isSplice =>
217213
if (inQuote) outer.checkType(pos).foldOver(acc, tp)
218214
else {
219215
spliceOutsideQuotes(pos)
@@ -328,13 +324,13 @@ class ReifyQuotes extends MacroTransform {
328324
quotation(arg, tree)
329325
case TypeApply(fn, arg :: Nil) if fn.symbol == defn.typeQuoteMethod =>
330326
quotation(arg, tree)
331-
case Select(body, _) if isSplice(tree.symbol) =>
327+
case Select(body, _) if tree.symbol.isSplice =>
332328
splice(body, tree)
333329
case Block(stats, _) =>
334330
val last = enteredSyms
335331
stats.foreach(markDef)
336332
mapOverTree(last)
337-
case Inlined(call, bindings, expansion @ Select(body, name)) if isSplice(expansion.symbol) =>
333+
case Inlined(call, bindings, expansion @ Select(body, name)) if expansion.symbol.isSplice =>
338334
// To maintain phase consistency, convert inlined expressions of the form
339335
// `{ bindings; ~expansion }` to `~{ bindings; expansion }`
340336
cpy.Select(expansion)(cpy.Inlined(tree)(call, bindings, body), name)

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,8 @@ class SymUtils(val self: Symbol) extends AnyVal {
175175
else if (owner.is(Package)) false
176176
else owner.isLocal
177177
}
178+
179+
/** Is symbol a splice operation? */
180+
def isSplice(implicit ctx: Context): Boolean =
181+
self == defn.QuotedExpr_~ || self == defn.QuotedType_~
178182
}

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

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -393,11 +393,24 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
393393
checkValue(assignType(cpy.Select(tree)(qual, tree.name), qual), pt)
394394

395395
def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = track("typedSelect") {
396+
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+
396406
def typeSelectOnTerm(implicit ctx: Context): Tree = {
397407
val qual1 = typedExpr(tree.qualifier, selectionProto(tree.name, pt, this))
398408
if (tree.name.isTypeName) checkStable(qual1.tpe, qual1.pos)
399409
val select = typedSelect(tree, pt, qual1)
400-
if (select.tpe ne TryDynamicCallType) select
410+
if (select.tpe ne TryDynamicCallType) {
411+
if (select.symbol.isSplice) markAsMacro(ctx)
412+
select
413+
}
401414
else if (pt.isInstanceOf[PolyProto] || pt.isInstanceOf[FunProto] || pt == AssignProto) select
402415
else typedDynamicSelect(tree, Nil, pt)
403416
}
@@ -1081,10 +1094,13 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
10811094
case AppliedType(_, argType :: Nil) => argType
10821095
case _ => WildcardType
10831096
}
1084-
if (isType)
1085-
ref(defn.typeQuoteMethod).appliedToTypeTrees(typedType(body, proto1) :: Nil)
1097+
val nestedCtx = ctx.fresh.setTree(tree)
1098+
if (isType) {
1099+
val body1 = typedType(body, proto1)(nestedCtx)
1100+
ref(defn.typeQuoteMethod).appliedToTypeTrees(body1 :: Nil)
1101+
}
10861102
else {
1087-
val body1 = typed(body, proto1)
1103+
val body1 = typed(body, proto1)(nestedCtx)
10881104
ref(defn.quoteMethod).appliedToType(body1.tpe.widen).appliedTo(body1)
10891105
}
10901106
}

0 commit comments

Comments
 (0)