Skip to content

Commit 8634edd

Browse files
committed
Move blackbox macro exapnsion to ReifyQuotes
1 parent adc44da commit 8634edd

File tree

11 files changed

+86
-41
lines changed

11 files changed

+86
-41
lines changed

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,7 @@ class ReifyQuotes extends MacroTransform {
207207
case splice: Select => cpy.Select(splice)(body1, splice.name)
208208
}
209209
}
210-
else {
211-
assert(level == 1, "unexpected top splice outside quote")
210+
else if (level == 1) {
212211
val (body1, quotes) = nested(isQuote = false).splitSplice(body)(spliceContext)
213212
val tpe = outer.embedded.getHoleType(body, splice)
214213
val hole = makeHole(splice.isTerm, body1, quotes, tpe).withSpan(splice.span)
@@ -218,6 +217,10 @@ class ReifyQuotes extends MacroTransform {
218217
// For example we can have a lifted tree containing the LHS of an assignment (see tests/run-with-compiler/quote-var.scala).
219218
if (splice.isType || outer.embedded.isLiftedSymbol(body.symbol)) hole
220219
else Inlined(EmptyTree, Nil, hole).withSpan(splice.span)
220+
} else {
221+
assert(level == 0, "unexpected splice insiced top splice")
222+
val newBody = Inliner.expandMacro(body, splice.span)
223+
transform(newBody)
221224
}
222225

223226
/** Transforms the contents of a nested splice

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

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

260279
/** Produces an inlined version of `call` via its `inlined` method.
@@ -1106,7 +1125,14 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
11061125
&& level == 0
11071126
&& call.symbol.is(Macro)
11081127
&& !suppressInline =>
1109-
expandMacro(res.args.head, tree.span)
1128+
val body = res.args.head
1129+
checkMacroDependencies(body, call.sourcePos)
1130+
if call.symbol.is(Synthetic) then
1131+
expandMacro(res.args.head, tree.span)
1132+
else
1133+
// Blackbox macros expanded later in ReifyQuotes
1134+
ctx.compilationUnit.needsStaging = true
1135+
res
11101136
case res => res
11111137
}
11121138

@@ -1264,32 +1290,16 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
12641290
}
12651291
}
12661292

1267-
private def expandMacro(body: Tree, span: Span)(implicit ctx: Context) = {
1293+
private def checkMacroDependencies(body: Tree, callPos: SourcePosition)(implicit ctx: Context): Unit = {
12681294
assert(level == 0)
1269-
val inlinedFrom = enclosingInlineds.last
12701295
val dependencies = macroDependencies(body)
1271-
12721296
if dependencies.nonEmpty && !ctx.reporter.errorsReported then
12731297
for sym <- dependencies do
12741298
if ctx.compilationUnit.source.file == sym.associatedFile then
1275-
ctx.error(em"Cannot call macro $sym defined in the same source file", call.sourcePos)
1299+
ctx.error(em"Cannot call macro $sym defined in the same source file", callPos)
12761300
if (ctx.settings.XprintSuspension.value)
1277-
ctx.echo(i"suspension triggered by macro call to ${sym.showLocated} in ${sym.associatedFile}", call.sourcePos)
1301+
ctx.echo(i"suspension triggered by macro call to ${sym.showLocated} in ${sym.associatedFile}", callPos)
12781302
ctx.compilationUnit.suspend() // this throws a SuspendException
1279-
1280-
val evaluatedSplice = {
1281-
given Context = tastyreflect.MacroExpansion.context(inlinedFrom)(using ctx)
1282-
Splicer.splice(body, inlinedFrom.sourcePos, MacroClassLoader.fromContext)
1283-
}
1284-
val inlinedNormailizer = new TreeMap {
1285-
override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match {
1286-
case Inlined(EmptyTree, Nil, expr) if enclosingInlineds.isEmpty => transform(expr)
1287-
case _ => super.transform(tree)
1288-
}
1289-
}
1290-
val normalizedSplice = inlinedNormailizer.transform(evaluatedSplice)
1291-
if (normalizedSplice.isEmpty) normalizedSplice
1292-
else normalizedSplice.withSpan(span)
12931303
}
12941304

12951305
/** 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
@@ -1744,6 +1744,12 @@ class Typer extends Namer
17441744
if (sym.isInlineMethod)
17451745
PrepareInlineable.registerInlineInfo(sym, _ => rhs1)
17461746

1747+
if (sym.isInlineMethod)
1748+
rhs1 match
1749+
case _: Typed =>
1750+
case _ => sym.setFlag(Synthetic) // FIXME Tag whitebox macros (do it in desugar)
1751+
1752+
17471753
if (sym.isConstructor && !sym.isPrimaryConstructor) {
17481754
val ename = sym.erasedName
17491755
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
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
DefDef("foo", Nil, Nil, Inferred(), None)
2-
ValDef("bar", Inferred(), None)
1+
DefDef("foo", Nil, Nil, TypeIdent("Int"), Some(Apply(Select(Literal(Constant(1)), "+"), List(Literal(Constant(2))))))
2+
ValDef("bar", TypeIdent("Int"), Some(Apply(Select(Literal(Constant(2)), "+"), List(Literal(Constant(3))))))
33
Bind("x", Ident("_"))

tests/run-custom-args/Yretain-trees/tasty-extractors-owners.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
foo
2-
ValDef("macro", Inferred(), None)
2+
DefDef("main", Nil, List(List(ValDef("args", Applied(TypeIdent("Array"), List(TypeIdent("String"))), None))), TypeIdent("Unit"), Some(Block(Nil, Inlined(Some(Projection(Inferred(), "Macros$")), Nil, Typed(Apply(TypeApply(Ident("exprSplice"), List(Inferred())), List(Block(List(DefDef("$anonfun", Nil, List(List(ValDef("evidence$1", Inferred(), None))), Inferred(), Some(Apply(Apply(TypeApply(Ident("impl"), List(Inferred())), List(Apply(Select(Apply(TypeApply(Ident("exprQuote"), List(Inferred())), List(Inlined(None, Nil, Block(List(DefDef("foo", Nil, Nil, Inferred(), Some(Block(List(DefDef("bar", Nil, Nil, Inferred(), Some(Literal(Constant(1)))), ValDef("bar2", Inferred(), Some(Literal(Constant(2))))), Typed(Ident("bar"), Inferred())))), ValDef("foo2", Inferred(), Some(Block(List(DefDef("baz", Nil, Nil, Inferred(), Some(Literal(Constant(3)))), ValDef("baz2", Inferred(), Some(Literal(Constant(4))))), Typed(Ident("baz"), Inferred())))), ClassDef("A", DefDef("<init>", Nil, List(Nil), Inferred(), None), List(Apply(Select(New(Inferred()), "<init>"), Nil)), Nil, None, List(TypeDef("B", TypeIdent("Int")), DefDef("b", Nil, Nil, Inferred(), Some(Literal(Constant(5)))), ValDef("b2", Inferred(), Some(Literal(Constant(6))))))), Literal(Constant(())))))), "apply"), List(Ident("evidence$1"))))), List(Ident("evidence$1")))))), Closure(Ident("$anonfun"), None)))), TypeIdent("Unit"))))))
33

44
bar
55
DefDef("foo", Nil, Nil, Inferred(), None)
@@ -8,7 +8,7 @@ bar2
88
DefDef("foo", Nil, Nil, Inferred(), None)
99

1010
foo2
11-
ValDef("macro", Inferred(), None)
11+
DefDef("main", Nil, List(List(ValDef("args", Applied(TypeIdent("Array"), List(TypeIdent("String"))), None))), TypeIdent("Unit"), Some(Block(Nil, Inlined(Some(Projection(Inferred(), "Macros$")), Nil, Typed(Apply(TypeApply(Ident("exprSplice"), List(Inferred())), List(Block(List(DefDef("$anonfun", Nil, List(List(ValDef("evidence$1", Inferred(), None))), Inferred(), Some(Apply(Apply(TypeApply(Ident("impl"), List(Inferred())), List(Apply(Select(Apply(TypeApply(Ident("exprQuote"), List(Inferred())), List(Inlined(None, Nil, Block(List(DefDef("foo", Nil, Nil, Inferred(), Some(Block(List(DefDef("bar", Nil, Nil, Inferred(), Some(Literal(Constant(1)))), ValDef("bar2", Inferred(), Some(Literal(Constant(2))))), Typed(Ident("bar"), Inferred())))), ValDef("foo2", Inferred(), Some(Block(List(DefDef("baz", Nil, Nil, Inferred(), Some(Literal(Constant(3)))), ValDef("baz2", Inferred(), Some(Literal(Constant(4))))), Typed(Ident("baz"), Inferred())))), ClassDef("A", DefDef("<init>", Nil, List(Nil), Inferred(), None), List(Apply(Select(New(Inferred()), "<init>"), Nil)), Nil, None, List(TypeDef("B", TypeIdent("Int")), DefDef("b", Nil, Nil, Inferred(), Some(Literal(Constant(5)))), ValDef("b2", Inferred(), Some(Literal(Constant(6))))))), Literal(Constant(())))))), "apply"), List(Ident("evidence$1"))))), List(Ident("evidence$1")))))), Closure(Ident("$anonfun"), None)))), TypeIdent("Unit"))))))
1212

1313
baz
1414
ValDef("foo2", Inferred(), None)
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
DefDef("foo", Nil, Nil, Inferred(), None)
2-
ValDef("bar", Inferred(), None)
1+
DefDef("foo", Nil, Nil, TypeIdent("Int"), Some(Apply(Select(Literal(Constant(1)), "+"), List(Literal(Constant(2))))))
2+
ValDef("bar", TypeIdent("Int"), Some(Apply(Select(Literal(Constant(2)), "+"), List(Literal(Constant(3))))))

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/reflect-sourceCode/Test_2.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ object Test {
99
assert(args( 0 /* ignore */).reflect == "args( 0 /* ignore */)")
1010
assert(f.reflect == "f")
1111
assert((f).reflect == "f")
12-
assert( { f }.reflect == "{ f }")
12+
assert( { f }.reflect == "f")
1313
assert( { f; f }.reflect == "{ f; f }")
1414
}
1515
}

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)