Skip to content

Commit f16a3fe

Browse files
committed
WIP Expand macros in typer
1 parent 7f4bd1c commit f16a3fe

24 files changed

+250
-75
lines changed

compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ object PickledQuotes {
145145
case Block(stats, expr) =>
146146
seq(stats, rec(expr)).withSpan(fn.span)
147147
case _ =>
148-
fn.select(nme.apply).appliedToArgs(argRefs())
148+
fn.select(nme.apply).appliedToArgs(argRefs()).withSpan(fn.span)
149149
}
150150
Block(argVals, rec(fn))
151151
}

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

+11-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import dotty.tools.dotc.ast.tpd
88
import dotty.tools.dotc.ast.Trees._
99
import dotty.tools.dotc.core.Contexts._
1010
import dotty.tools.dotc.core.Decorators._
11-
import dotty.tools.dotc.core.Flags._
11+
import dotty.tools.dotc.core.Flags.{Method => MethodFlag, _}
1212
import dotty.tools.dotc.core.NameKinds.FlatName
1313
import dotty.tools.dotc.core.Names.{Name, TermName}
1414
import dotty.tools.dotc.core.StdNames._
@@ -95,7 +95,7 @@ object Splicer {
9595
}
9696

9797
protected def interpretQuote(tree: Tree)(implicit env: Env): Object =
98-
new scala.quoted.Exprs.TastyTreeExpr(tree)
98+
new scala.quoted.Exprs.TastyTreeExpr(Inlined(EmptyTree, Nil, tree).withSpan(tree.span))
9999

100100
protected def interpretTypeQuote(tree: Tree)(implicit env: Env): Object =
101101
new scala.quoted.Types.TreeType(tree)
@@ -312,7 +312,13 @@ object Splicer {
312312

313313
protected final def interpretTree(tree: Tree)(implicit env: Env): Result = tree match {
314314
case Apply(TypeApply(fn, _), quoted :: Nil) if fn.symbol == defn.QuotedExpr_apply =>
315-
interpretQuote(quoted)
315+
val quoted1 = quoted match {
316+
case quoted: Ident if quoted.symbol.is(InlineProxy) && quoted.symbol.is(MethodFlag) => // inline proxy for by-name parameter
317+
// TODO stop generating inline proxies for by-name parameter and remove this special case
318+
quoted.symbol.defTree.asInstanceOf[DefDef].rhs
319+
case _ => quoted
320+
}
321+
interpretQuote(quoted1)
316322

317323
case TypeApply(fn, quoted :: Nil) if fn.symbol == defn.QuotedType_apply =>
318324
interpretTypeQuote(quoted)
@@ -336,6 +342,8 @@ object Splicer {
336342
interpretStaticMethodCall(module, fn.symbol, args.map(arg => interpretTree(arg)))
337343
} else if (env.contains(fn.name)) {
338344
env(fn.name)
345+
} else if (tree.symbol.is(InlineProxy)) {
346+
interpretTree(tree.symbol.defTree.asInstanceOf[ValOrDefDef].rhs)
339347
} else {
340348
unexpectedTree(tree)
341349
}

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

+16-19
Original file line numberDiff line numberDiff line change
@@ -122,25 +122,22 @@ object Staging {
122122
if (splice1.isType) splice1
123123
else addSpliceCast(splice1)
124124
}
125-
else if (enclosingInlineds.nonEmpty) { // level 0 in an inlined call
126-
val spliceCtx = ctx.outer // drop the last `inlineContext`
127-
val pos: SourcePosition = spliceCtx.source.atSpan(enclosingInlineds.head.span)
128-
val evaluatedSplice = Splicer.splice(splice.qualifier, pos, macroClassLoader)(spliceCtx)
129-
if (ctx.reporter.hasErrors) splice else transform(evaluatedSplice.withSpan(splice.span))
130-
}
131-
else if (!ctx.owner.isInlineMethod) { // level 0 outside an inline method
132-
ctx.error(i"splice outside quotes or inline method", splice.sourcePos)
133-
splice
134-
}
135-
else if (Splicer.canBeSpliced(splice.qualifier)) { // level 0 inside an inline definition
136-
transform(splice.qualifier)(spliceContext) // Just check PCP
137-
splice
138-
}
139-
else { // level 0 inside an inline definition
140-
ctx.error(
141-
"Malformed macro call. The contents of the ~ must call a static method and arguments must be quoted or inline.",
142-
splice.sourcePos)
143-
splice
125+
else {
126+
assert(!enclosingInlineds.nonEmpty, "unexpanded macro")
127+
if (!ctx.owner.isInlineMethod) { // level 0 outside an inline method
128+
ctx.error(i"splice outside quotes or inline method", splice.sourcePos)
129+
splice
130+
}
131+
else if (Splicer.canBeSpliced(splice.qualifier)) { // level 0 inside an inline definition
132+
transform(splice.qualifier)(spliceContext) // Just check PCP
133+
splice
134+
}
135+
else { // level 0 inside an inline definition
136+
ctx.error(
137+
"Malformed macro call. The contents of the $ must call a static method and arguments must be quoted or inline.",
138+
splice.sourcePos)
139+
splice
140+
}
144141
}
145142
}
146143

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ abstract class Lifter {
4747
var liftedType = expr.tpe.widen
4848
if (liftedFlags.is(Method)) liftedType = ExprType(liftedType)
4949
val lifted = ctx.newSymbol(ctx.owner, name, liftedFlags | Synthetic, liftedType, coord = spanCoord(expr.span))
50-
defs += liftedDef(lifted, expr).withSpan(expr.span)
50+
val ddef = liftedDef(lifted, expr).withSpan(expr.span)
51+
lifted.defTree = ddef
52+
defs += ddef
5153
ref(lifted.termRef).withSpan(expr.span.focus)
5254
}
5355

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

+34-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package dotty.tools
22
package dotc
33
package typer
44

5-
import ast._
5+
import ast.{TreeInfo, tpd, _}
66
import Trees._
77
import core._
88
import Flags._
@@ -25,6 +25,7 @@ import dotty.tools.dotc.util.{SimpleIdentityMap, SimpleIdentitySet, SourceFile,
2525
import collection.mutable
2626
import reporting.trace
2727
import util.Spans.Span
28+
import dotty.tools.dotc.transform.{Splicer, TreeMapWithStages}
2829

2930
object Inliner {
3031
import tpd._
@@ -104,7 +105,7 @@ object Inliner {
104105
else if (enclosingInlineds.length < ctx.settings.XmaxInlines.value) {
105106
val body = bodyToInline(tree.symbol) // can typecheck the tree and thereby produce errors
106107
if (ctx.reporter.hasErrors) tree
107-
else new Inliner(tree, body).inlined(pt)
108+
else new Inliner(tree, body).inlined(pt, tree.sourcePos)
108109
}
109110
else
110111
errorTree(
@@ -381,7 +382,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
381382
}
382383

383384
/** The Inlined node representing the inlined call */
384-
def inlined(pt: Type): Tree = {
385+
def inlined(pt: Type, sourcePos: SourcePosition): Tree = {
385386

386387
if (callTypeArgs.length == 1)
387388
if (inlinedMethod == defn.Compiletime_constValue) {
@@ -487,10 +488,21 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
487488
trace(i"inlining $call", inlining, show = true) {
488489

489490
// The normalized bindings collected in `bindingsBuf`
490-
bindingsBuf.transform(reducer.normalizeBinding(_)(inlineCtx))
491+
bindingsBuf.transform { binding =>
492+
val transformedBinding = reducer.normalizeBinding(binding)(inlineCtx)
493+
// Set trees to symbols allow macros to see the definition tree.
494+
// This is used by `underlyingArgument`.
495+
transformedBinding.symbol.defTree = transformedBinding
496+
transformedBinding
497+
}
498+
499+
// Evaluate the top level ~ if it is a macro
500+
val expansion0 =
501+
if (call.symbol.is(Macro) && TreeMapWithStages.level == 0) expandMacro(expansion, sourcePos)
502+
else expansion
491503

492504
// Run a typing pass over the inlined tree. See InlineTyper for details.
493-
val expansion1 = inlineTyper.typed(expansion, pt)(inlineCtx)
505+
val expansion1 = inlineTyper.typed(expansion0, pt)(inlineCtx)
494506

495507
if (ctx.settings.verbose.value) {
496508
inlining.println(i"to inline = $rhsToInline")
@@ -509,6 +521,23 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
509521
}
510522
}
511523

524+
private def expandMacro(expansion: Tree, pos: SourcePosition) = {
525+
// TODO cache macro classloader
526+
val urls = ctx.settings.classpath.value.split(java.io.File.pathSeparatorChar).map(cp => java.nio.file.Paths.get(cp).toUri.toURL)
527+
val macroClassLoader = new java.net.URLClassLoader(urls, getClass.getClassLoader)
528+
529+
new TreeMap() {
530+
override def transform(tree1: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree1 match {
531+
case Spliced(splicedBody) =>
532+
val evaluatedSplice = Splicer.splice(splicedBody, pos, macroClassLoader)
533+
if (ctx.reporter.hasErrors) EmptyTree
534+
else evaluatedSplice.withSpan(tree1.span)
535+
case _ =>
536+
super.transform(tree1)
537+
}
538+
}.transform(expansion)
539+
}
540+
512541
/** A utility object offering methods for rewriting inlined code */
513542
object reducer {
514543

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import scala.quoted._
2+
3+
object Macros {
4+
inline def defaultOf(inline str: String) <: Any = ${ defaultOfImpl(str) }
5+
def defaultOfImpl(str: String): Expr[Any] = str match {
6+
case "int" => '{1}
7+
case "string" => '{"a"}
8+
}
9+
}

tests/neg/quote-whitebox/Test_2.scala

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import Macros._
2+
3+
object Test {
4+
def main(args: Array[String]): Unit = {
5+
val a: String = defaultOf("int") // error
6+
val b: Int = defaultOf("string") // error
7+
}
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
import Asserts._
3+
4+
object Test {
5+
def main(args: Array[String]): Unit = {
6+
macroAssert(true === "cde")
7+
macroAssert("acb" === "cde") // error
8+
}
9+
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import scala.quoted._
2+
3+
import scala.tasty._
4+
5+
object Asserts {
6+
7+
implicit class Ops[T](left: T) {
8+
def ===(right: T): Boolean = left == right
9+
def !==(right: T): Boolean = left != right
10+
}
11+
12+
object Ops
13+
14+
inline def macroAssert(cond: => Boolean): Unit =
15+
${ impl('cond) }
16+
17+
def impl(cond: Expr[Boolean])(implicit reflect: Reflection): Expr[Unit] = {
18+
import reflect._
19+
20+
val tree = cond.unseal
21+
22+
def isOps(tpe: TypeOrBounds): Boolean = tpe match {
23+
case Type.SymRef(IsDefSymbol(sym), _) => sym.name == "Ops" // TODO check that the parent is Asserts
24+
case _ => false
25+
}
26+
27+
object OpsTree {
28+
def unapply(arg: Term): Option[Term] = arg match {
29+
case Term.Apply(Term.TypeApply(term, _), left :: Nil) if isOps(term.tpe) =>
30+
Some(left)
31+
case _ => None
32+
}
33+
}
34+
35+
tree match {
36+
case Term.Inlined(_, Nil, Term.Apply(Term.Select(OpsTree(left), op), right :: Nil)) =>
37+
'{assertTrue(${left.seal[Boolean]})} // Buggy code. To generate the errors
38+
case _ =>
39+
'{assertTrue($cond)}
40+
}
41+
42+
}
43+
44+
def assertEquals[T](left: T, right: T): Unit = {
45+
if (left != right) {
46+
println(
47+
s"""Error left did not equal right:
48+
| left = $left
49+
| right = $right""".stripMargin)
50+
}
51+
52+
}
53+
54+
def assertNotEquals[T](left: T, right: T): Unit = {
55+
if (left == right) {
56+
println(
57+
s"""Error left was equal to right:
58+
| left = $left
59+
| right = $right""".stripMargin)
60+
}
61+
62+
}
63+
64+
def assertTrue(cond: Boolean): Unit = {
65+
if (!cond)
66+
println("Condition was false")
67+
}
68+
69+
}

tests/neg/tasty-macro-assert/quoted_2.scala renamed to tests/neg/tasty-macro-assert-2/quoted_2.scala

-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import Asserts._
33

44
object Test {
55
def main(args: Array[String]): Unit = {
6-
macroAssert(true === "cde")
7-
macroAssert("acb" === "cde") // error
86
macroAssert(false !== "acb")
97
macroAssert("acb" !== "acb") // error
108
}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
DefDef("foo", Nil, Nil, TypeTree.Ident("Int"), Some(Term.Apply(Term.Select(Term.Literal(Constant.Int(1)), "+"), List(Term.Literal(Constant.Int(2))))))
2-
ValDef("bar", TypeTree.Ident("Int"), Some(Term.Apply(Term.Select(Term.Literal(Constant.Int(2)), "+"), List(Term.Literal(Constant.Int(3))))))
1+
DefDef("foo", Nil, Nil, TypeTree.Inferred(), None)
2+
ValDef("bar", TypeTree.Inferred(), None)
33
Pattern.Bind("x", Pattern.Value(Term.Ident("_")))
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
foo
2-
DefDef("main", Nil, List(List(ValDef("args", TypeTree.Applied(TypeTree.Ident("Array"), List(TypeTree.Ident("String"))), None))), TypeTree.Ident("Unit"), Some(Term.Block(Nil, Term.Inlined(Some(Term.Apply(Term.TypeApply(Term.Ident("printOwners"), List(TypeTree.Inferred())), List(Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Inferred(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Inferred())))), ValDef("foo2", TypeTree.Inferred(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Inferred())))), ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), Nil)), Nil, None, List(TypeDef("B", TypeTree.Ident("Int")), DefDef("b", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit()))))), Nil, Term.Typed(Term.Select(Term.Apply(Term.Apply(Term.TypeApply(Term.Ident("impl"), List(TypeTree.Inferred())), List(Term.Apply(Term.TypeApply(Term.Ident("apply"), List(TypeTree.Inferred())), List(Term.Inlined(None, Nil, Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Inferred(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Inferred())))), ValDef("foo2", TypeTree.Inferred(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Inferred())))), ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), Nil)), Nil, None, List(TypeDef("B", TypeTree.Ident("Int")), DefDef("b", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit()))))))), List(Term.Ident("macroContext"))), "splice"), TypeTree.Ident("Unit"))))))
2+
DefDef("main", Nil, List(List(ValDef("args", TypeTree.Inferred(), None))), TypeTree.Inferred(), None)
33

44
bar
5-
DefDef("foo", Nil, Nil, TypeTree.Inferred(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Inferred()))))
5+
DefDef("foo", Nil, Nil, TypeTree.Inferred(), None)
66

77
bar2
8-
DefDef("foo", Nil, Nil, TypeTree.Inferred(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Inferred()))))
8+
DefDef("foo", Nil, Nil, TypeTree.Inferred(), None)
99

1010
foo2
11-
DefDef("main", Nil, List(List(ValDef("args", TypeTree.Applied(TypeTree.Ident("Array"), List(TypeTree.Ident("String"))), None))), TypeTree.Ident("Unit"), Some(Term.Block(Nil, Term.Inlined(Some(Term.Apply(Term.TypeApply(Term.Ident("printOwners"), List(TypeTree.Inferred())), List(Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Inferred(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Inferred())))), ValDef("foo2", TypeTree.Inferred(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Inferred())))), ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), Nil)), Nil, None, List(TypeDef("B", TypeTree.Ident("Int")), DefDef("b", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit()))))), Nil, Term.Typed(Term.Select(Term.Apply(Term.Apply(Term.TypeApply(Term.Ident("impl"), List(TypeTree.Inferred())), List(Term.Apply(Term.TypeApply(Term.Ident("apply"), List(TypeTree.Inferred())), List(Term.Inlined(None, Nil, Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Inferred(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Inferred())))), ValDef("foo2", TypeTree.Inferred(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Inferred())))), ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Inferred()), "<init>"), Nil)), Nil, None, List(TypeDef("B", TypeTree.Ident("Int")), DefDef("b", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit()))))))), List(Term.Ident("macroContext"))), "splice"), TypeTree.Ident("Unit"))))))
11+
DefDef("main", Nil, List(List(ValDef("args", TypeTree.Inferred(), None))), TypeTree.Inferred(), None)
1212

1313
baz
14-
ValDef("foo2", TypeTree.Inferred(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Inferred()))))
14+
ValDef("foo2", TypeTree.Inferred(), None)
1515

1616
baz2
17-
ValDef("foo2", TypeTree.Inferred(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Inferred()))))
17+
ValDef("foo2", TypeTree.Inferred(), None)
1818

1919
<init>
20-
ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(TypeTree.Inferred()), Nil, None, List(TypeDef("B", TypeBoundsTree(TypeTree.Inferred(), TypeTree.Inferred())), DefDef("b", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(6))))))
20+
ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(TypeTree.Inferred()), Nil, None, List(TypeDef("B", TypeBoundsTree(TypeTree.Inferred(), TypeTree.Inferred())), DefDef("b", Nil, Nil, TypeTree.Inferred(), None), ValDef("b2", TypeTree.Inferred(), None)))
2121

2222
b
23-
ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(TypeTree.Inferred()), Nil, None, List(TypeDef("B", TypeBoundsTree(TypeTree.Inferred(), TypeTree.Inferred())), DefDef("b", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(6))))))
23+
ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(TypeTree.Inferred()), Nil, None, List(TypeDef("B", TypeBoundsTree(TypeTree.Inferred(), TypeTree.Inferred())), DefDef("b", Nil, Nil, TypeTree.Inferred(), None), ValDef("b2", TypeTree.Inferred(), None)))
2424

2525
b2
26-
ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(TypeTree.Inferred()), Nil, None, List(TypeDef("B", TypeBoundsTree(TypeTree.Inferred(), TypeTree.Inferred())), DefDef("b", Nil, Nil, TypeTree.Inferred(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Inferred(), Some(Term.Literal(Constant.Int(6))))))
26+
ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Inferred(), None), List(TypeTree.Inferred()), Nil, None, List(TypeDef("B", TypeBoundsTree(TypeTree.Inferred(), TypeTree.Inferred())), DefDef("b", Nil, Nil, TypeTree.Inferred(), None), ValDef("b2", TypeTree.Inferred(), None)))
2727

Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
DefDef("foo", Nil, Nil, TypeTree.Ident("Int"), Some(Term.Apply(Term.Select(Term.Literal(Constant.Int(1)), "+"), List(Term.Literal(Constant.Int(2))))))
2-
ValDef("bar", TypeTree.Ident("Int"), Some(Term.Apply(Term.Select(Term.Literal(Constant.Int(2)), "+"), List(Term.Literal(Constant.Int(3))))))
1+
DefDef("foo", Nil, Nil, TypeTree.Inferred(), None)
2+
ValDef("bar", TypeTree.Inferred(), None)

tests/run-with-compiler/quote-macro-in-splice.check

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import scala.quoted._
2+
3+
object Macros {
4+
def impl(x: Expr[Int]): Expr[Int] = '{ $x + 1 }
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import scala.quoted._
2+
import Macros._
3+
4+
import scala.quoted.Toolbox.Default._
5+
6+
object Test {
7+
def main(args: Array[String]): Unit = {
8+
val x = '{
9+
val y = 1
10+
${
11+
inline def a(z: Int): Int = ${ impl('z) }
12+
val b = a(7).toExpr
13+
'{ y + $b }
14+
}
15+
}
16+
println(x.show)
17+
}
18+
19+
}

tests/run/quote-whitebox.check

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
1
2+
a

0 commit comments

Comments
 (0)