Skip to content

Commit acac110

Browse files
committed
Move blackbox macro exapnsion to ReifyQuotes
1 parent 2bacda6 commit acac110

File tree

7 files changed

+79
-33
lines changed

7 files changed

+79
-33
lines changed

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,7 @@ class ReifyQuotes extends MacroTransform {
261261
case splice: Select => cpy.Select(splice)(body1, splice.name)
262262
}
263263
}
264-
else {
265-
assert(level == 1, "unexpected top splice outside quote")
264+
else if (level == 1) {
266265
val (body1, quotes) = nested(isQuote = false).splitSplice(body)(spliceContext)
267266
val tpe = outer.embedded.getHoleType(body, splice)
268267
val hole = makeHole(splice.isTerm, body1, quotes, tpe).withSpan(splice.span)
@@ -272,6 +271,10 @@ class ReifyQuotes extends MacroTransform {
272271
// For example we can have a lifted tree containing the LHS of an assignment (see tests/run-with-compiler/quote-var.scala).
273272
if (splice.isType || outer.embedded.isLiftedSymbol(body.symbol)) hole
274273
else Inlined(EmptyTree, Nil, hole).withSpan(splice.span)
274+
} else {
275+
assert(level == 0, "unexpected splice insiced top splice")
276+
val newBody = Inliner.expandMacro(body, splice.span)
277+
transform(newBody)
275278
}
276279

277280
/** Transforms the contents of a nested splice

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

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,25 @@ object Inliner {
254254
val errors = compileForErrors(tree, false)
255255
packErrors(errors)
256256
}
257+
258+
def expandMacro(body: Tree, span: Span)(implicit ctx: Context) = {
259+
assert(level == 0)
260+
val inlinedFrom = enclosingInlineds.last
261+
val ctx1 = tastyreflect.MacroExpansion.context(inlinedFrom)
262+
263+
val evaluatedSplice = Splicer.splice(body, inlinedFrom.sourcePos, MacroClassLoader.fromContext)(ctx1)
264+
265+
val inlinedNormailizer = new TreeMap {
266+
override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match {
267+
case Inlined(EmptyTree, Nil, expr) if enclosingInlineds.isEmpty => transform(expr)
268+
case _ => super.transform(tree)
269+
}
270+
}
271+
val normalizedSplice = inlinedNormailizer.transform(evaluatedSplice)
272+
if (normalizedSplice.isEmpty) normalizedSplice
273+
else normalizedSplice.withSpan(span)
274+
}
275+
257276
}
258277

259278
/** Produces an inlined version of `call` via its `inlined` method.
@@ -1110,7 +1129,14 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
11101129
&& level == 0
11111130
&& call.symbol.is(Macro)
11121131
&& !suppressInline =>
1113-
expandMacro(res.args.head, tree.span)
1132+
val body = res.args.head
1133+
checkMacroDependencies(body, call.sourcePos)
1134+
if call.symbol.is(Synthetic) then
1135+
expandMacro(res.args.head, tree.span)
1136+
else
1137+
// Blackbox macros expanded later in ReifyQuotes
1138+
ctx.compilationUnit.needsStaging = true
1139+
res
11141140
case res => res
11151141
}
11161142

@@ -1269,31 +1295,16 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
12691295
}
12701296
}
12711297

1272-
private def expandMacro(body: Tree, span: Span)(implicit ctx: Context) = {
1298+
private def checkMacroDependencies(body: Tree, callPos: SourcePosition)(implicit ctx: Context): Unit = {
12731299
assert(level == 0)
1274-
val inlinedFrom = enclosingInlineds.last
1275-
val ctx1 = tastyreflect.MacroExpansion.context(inlinedFrom)
12761300
val dependencies = macroDependencies(body)
1277-
12781301
if dependencies.nonEmpty && !ctx.reporter.errorsReported then
12791302
for sym <- dependencies do
12801303
if ctx.compilationUnit.source.file == sym.associatedFile then
1281-
ctx.error(em"Cannot call macro $sym defined in the same source file", call.sourcePos)
1304+
ctx.error(em"Cannot call macro $sym defined in the same source file", callPos)
12821305
if (ctx.settings.XprintSuspension.value)
1283-
ctx.echo(i"suspension triggered by macro call to ${sym.showLocated} in ${sym.associatedFile}", call.sourcePos)
1306+
ctx.echo(i"suspension triggered by macro call to ${sym.showLocated} in ${sym.associatedFile}", callPos)
12841307
ctx.compilationUnit.suspend() // this throws a SuspendException
1285-
1286-
val evaluatedSplice = Splicer.splice(body, inlinedFrom.sourcePos, MacroClassLoader.fromContext)(ctx1)
1287-
1288-
val inlinedNormailizer = new TreeMap {
1289-
override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match {
1290-
case Inlined(EmptyTree, Nil, expr) if enclosingInlineds.isEmpty => transform(expr)
1291-
case _ => super.transform(tree)
1292-
}
1293-
}
1294-
val normalizedSplice = inlinedNormailizer.transform(evaluatedSplice)
1295-
if (normalizedSplice.isEmpty) normalizedSplice
1296-
else normalizedSplice.withSpan(span)
12971308
}
12981309

12991310
/** Return the set of symbols that are referred at level -1 by the tree and defined in the current run.

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,6 +1655,12 @@ class Typer extends Namer
16551655
if (sym.isInlineMethod)
16561656
PrepareInlineable.registerInlineInfo(sym, _ => rhs1)
16571657

1658+
if (sym.isInlineMethod)
1659+
rhs1 match
1660+
case _: Typed =>
1661+
case _ => sym.setFlag(Synthetic) // FIXME Tag whitebox macros (do it in desugar)
1662+
1663+
16581664
if (sym.isConstructor && !sym.isPrimaryConstructor) {
16591665
val ename = sym.erasedName
16601666
if (ename != sym.name)

tests/neg/i6530.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
object Macros {
22
inline def q : Int = ${ '[ Int ] } // error
3-
val x : Int = 1 + q // error
3+
val x : Int = 1 + q
4+
5+
inline def q2 <: Int = ${ '[ Int ] } // error
6+
val y : Int = 1 + q2 // error
47
}

tests/run-macros/box/Macro_1.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import scala.quoted._
2+
3+
object Macros {
4+
5+
inline def blackbox: Int = ${one}
6+
7+
inline def whitebox <: Int = ${one}
8+
9+
private def one(given QuoteContext): Expr[Int] = Expr(1)
10+
11+
}

tests/run-macros/box/Test_2.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import scala.quoted._
2+
import Macros._
3+
4+
object Test {
5+
def main(args: Array[String]): Unit = {
6+
val a: Int = blackbox
7+
val b: 1 = whitebox
8+
9+
assert(a == 1)
10+
assert(b == 1)
11+
}
12+
}

tests/run-macros/tasty-extractors-1.check

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,40 +37,40 @@ ConstantType(Constant(3))
3737
Inlined(None, Nil, If(Typed(Literal(Constant(true)), TypeIdent("Boolean")), Literal(Constant(1)), Literal(Constant(2))))
3838
OrType(ConstantType(Constant(1)), ConstantType(Constant(2)))
3939

40-
Inlined(None, Nil, Match(Literal(Constant("a")), List(CaseDef(Literal(Constant("a")), None, Block(Nil, Literal(Constant(())))))))
40+
Inlined(None, Nil, Match(Literal(Constant("a")), List(CaseDef(Literal(Constant("a")), None, Literal(Constant(()))))))
4141
TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Unit")
4242

43-
Inlined(None, Nil, Match(Literal(Constant("b")), List(CaseDef(Bind("n", Ident("_")), None, Block(Nil, Literal(Constant(())))))))
43+
Inlined(None, Nil, Match(Literal(Constant("b")), List(CaseDef(Bind("n", Ident("_")), None, Literal(Constant(()))))))
4444
TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Unit")
4545

46-
Inlined(None, Nil, Match(Literal(Constant("c")), List(CaseDef(Bind("n", Typed(Ident("_"), TypeIdent("String"))), None, Block(Nil, Literal(Constant(())))))))
46+
Inlined(None, Nil, Match(Literal(Constant("c")), List(CaseDef(Bind("n", Typed(Ident("_"), TypeIdent("String"))), None, Literal(Constant(()))))))
4747
TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Unit")
4848

49-
Inlined(None, Nil, Match(Literal(Constant("e")), List(CaseDef(Ident("_"), None, Block(Nil, Literal(Constant(())))))))
49+
Inlined(None, Nil, Match(Literal(Constant("e")), List(CaseDef(Ident("_"), None, Literal(Constant(()))))))
5050
TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Unit")
5151

52-
Inlined(None, Nil, Match(Literal(Constant("f")), List(CaseDef(Typed(Ident("_"), TypeIdent("String")), None, Block(Nil, Literal(Constant(())))))))
52+
Inlined(None, Nil, Match(Literal(Constant("f")), List(CaseDef(Typed(Ident("_"), TypeIdent("String")), None, Literal(Constant(()))))))
5353
TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Unit")
5454

55-
Inlined(None, Nil, Match(Typed(Literal(Constant("g")), TypeIdent("Any")), List(CaseDef(Alternative(List(Typed(Ident("_"), TypeIdent("String")), Typed(Ident("_"), TypeIdent("Int")))), None, Block(Nil, Literal(Constant(())))))))
55+
Inlined(None, Nil, Match(Typed(Literal(Constant("g")), TypeIdent("Any")), List(CaseDef(Alternative(List(Typed(Ident("_"), TypeIdent("String")), Typed(Ident("_"), TypeIdent("Int")))), None, Literal(Constant(()))))))
5656
TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Unit")
5757

58-
Inlined(None, Nil, Match(Literal(Constant("h")), List(CaseDef(Ident("_"), Some(Literal(Constant(false))), Block(Nil, Literal(Constant(())))))))
58+
Inlined(None, Nil, Match(Literal(Constant("h")), List(CaseDef(Ident("_"), Some(Literal(Constant(false))), Literal(Constant(()))))))
5959
TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Unit")
6060

61-
Inlined(None, Nil, Block(List(ValDef("a", Inferred(), Some(Literal(Constant("o"))))), Match(Literal(Constant("i")), List(CaseDef(Bind("a", Ident("_")), None, Block(Nil, Literal(Constant(()))))))))
61+
Inlined(None, Nil, Block(List(ValDef("a", Inferred(), Some(Literal(Constant("o"))))), Match(Literal(Constant("i")), List(CaseDef(Bind("a", Ident("_")), None, Literal(Constant(())))))))
6262
TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Unit")
6363

64-
Inlined(None, Nil, Match(Ident("Nil"), List(CaseDef(Unapply(TypeApply(Select(Ident("List"), "unapplySeq"), List(Inferred())), Nil, List(Bind("a", Ident("_")), Bind("b", Ident("_")), Bind("c", Ident("_")))), None, Block(Nil, Literal(Constant(())))))))
64+
Inlined(None, Nil, Match(Ident("Nil"), List(CaseDef(Unapply(TypeApply(Select(Ident("List"), "unapplySeq"), List(Inferred())), Nil, List(Bind("a", Ident("_")), Bind("b", Ident("_")), Bind("c", Ident("_")))), None, Literal(Constant(()))))))
6565
TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Unit")
6666

67-
Inlined(None, Nil, Try(Literal(Constant(1)), List(CaseDef(Ident("_"), None, Block(Nil, Literal(Constant(()))))), None))
67+
Inlined(None, Nil, Try(Literal(Constant(1)), List(CaseDef(Ident("_"), None, Literal(Constant(())))), None))
6868
OrType(ConstantType(Constant(1)), TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Unit"))
6969

7070
Inlined(None, Nil, Try(Literal(Constant(2)), Nil, Some(Literal(Constant(())))))
7171
ConstantType(Constant(2))
7272

73-
Inlined(None, Nil, Try(Literal(Constant(3)), List(CaseDef(Ident("_"), None, Block(Nil, Literal(Constant(()))))), Some(Literal(Constant(())))))
73+
Inlined(None, Nil, Try(Literal(Constant(3)), List(CaseDef(Ident("_"), None, Literal(Constant(())))), Some(Literal(Constant(())))))
7474
OrType(ConstantType(Constant(3)), TypeRef(ThisType(TypeRef(NoPrefix(), "scala")), "Unit"))
7575

7676
Inlined(None, Nil, Apply(Select(Literal(Constant("a")), "=="), List(Literal(Constant("b")))))

0 commit comments

Comments
 (0)