Skip to content

Commit 0e3c9a4

Browse files
committed
Move blackbox macro exapnsion to ReifyQuotes
1 parent 193f7de commit 0e3c9a4

File tree

11 files changed

+86
-40
lines changed

11 files changed

+86
-40
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.
@@ -1112,7 +1131,14 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
11121131
&& level == 0
11131132
&& call.symbol.is(Macro)
11141133
&& !suppressInline =>
1115-
expandMacro(res.args.head, tree.span)
1134+
val body = res.args.head
1135+
checkMacroDependencies(body, call.sourcePos)
1136+
if call.symbol.is(Synthetic) then
1137+
expandMacro(res.args.head, tree.span)
1138+
else
1139+
// Blackbox macros expanded later in ReifyQuotes
1140+
ctx.compilationUnit.needsStaging = true
1141+
res
11161142
case res => res
11171143
}
11181144

@@ -1270,31 +1296,16 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
12701296
}
12711297
}
12721298

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

13001311
/** 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
@@ -1676,6 +1676,12 @@ class Typer extends Namer
16761676
if (sym.isInlineMethod)
16771677
PrepareInlineable.registerInlineInfo(sym, _ => rhs1)
16781678

1679+
if (sym.isInlineMethod)
1680+
rhs1 match
1681+
case _: Typed =>
1682+
case _ => sym.setFlag(Synthetic) // FIXME Tag whitebox macros (do it in desugar)
1683+
1684+
16791685
if (sym.isConstructor && !sym.isPrimaryConstructor) {
16801686
val ename = sym.erasedName
16811687
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-
DefDef("main", Nil, List(List(ValDef("args", Inferred(), None))), 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-
DefDef("main", Nil, List(List(ValDef("args", Inferred(), None))), 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/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")))))

tests/run-with-compiler/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
}

0 commit comments

Comments
 (0)