Skip to content

Commit 20447f1

Browse files
committed
WIP Expand macros in typer
1 parent 6c0cce7 commit 20447f1

File tree

21 files changed

+228
-77
lines changed

21 files changed

+228
-77
lines changed

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).withSpan(splice.span)
129-
if (ctx.reporter.hasErrors) splice else transform(evaluatedSplice)
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

+35-6
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._
@@ -26,7 +26,8 @@ import collection.mutable
2626
import reporting.trace
2727
import util.Spans.Span
2828
import util.SourcePosition
29-
import ast.TreeInfo
29+
import dotty.tools.dotc.core.quoted.Spliced
30+
import dotty.tools.dotc.transform.{Splicer, TreeMapWithStages}
3031

3132
object Inliner {
3233
import tpd._
@@ -106,7 +107,7 @@ object Inliner {
106107
else if (enclosingInlineds.length < ctx.settings.XmaxInlines.value) {
107108
val body = bodyToInline(tree.symbol) // can typecheck the tree and thereby produce errors
108109
if (ctx.reporter.hasErrors) tree
109-
else new Inliner(tree, body).inlined(pt)
110+
else new Inliner(tree, body).inlined(pt, tree.sourcePos)
110111
}
111112
else
112113
errorTree(
@@ -359,7 +360,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
359360
}
360361

361362
/** The Inlined node representing the inlined call */
362-
def inlined(pt: Type): Tree = {
363+
def inlined(pt: Type, sourcePos: SourcePosition): Tree = {
363364

364365
if (callTypeArgs.length == 1)
365366
if (inlinedMethod == defn.Compiletime_constValue) {
@@ -465,10 +466,21 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
465466
trace(i"inlining $call", inlining, show = true) {
466467

467468
// The normalized bindings collected in `bindingsBuf`
468-
bindingsBuf.transform(reducer.normalizeBinding(_)(inlineCtx))
469+
bindingsBuf.transform { binding =>
470+
val transformedBinding = reducer.normalizeBinding(binding)(inlineCtx)
471+
// Set trees to symbols allow macros to see the definition tree.
472+
// This is used by `underlyingArgument`.
473+
transformedBinding.symbol.defTree = transformedBinding
474+
transformedBinding
475+
}
476+
477+
// Evaluate the top level ~ if it is a macro
478+
val expansion0 =
479+
if (call.symbol.is(Macro) && TreeMapWithStages.level == 0) expandMacro(expansion, sourcePos)
480+
else expansion
469481

470482
// Run a typing pass over the inlined tree. See InlineTyper for details.
471-
val expansion1 = inlineTyper.typed(expansion, pt)(inlineCtx)
483+
val expansion1 = inlineTyper.typed(expansion0, pt)(inlineCtx)
472484

473485
if (ctx.settings.verbose.value) {
474486
inlining.println(i"to inline = $rhsToInline")
@@ -487,6 +499,23 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
487499
}
488500
}
489501

502+
private def expandMacro(expansion: Tree, pos: SourcePosition) = {
503+
// TODO cache macro classloader
504+
val urls = ctx.settings.classpath.value.split(java.io.File.pathSeparatorChar).map(cp => java.nio.file.Paths.get(cp).toUri.toURL)
505+
val macroClassLoader = new java.net.URLClassLoader(urls, getClass.getClassLoader)
506+
507+
new TreeMap() {
508+
override def transform(tree1: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree1 match {
509+
case Spliced(splicedBody) =>
510+
val evaluatedSplice = Splicer.splice(splicedBody, pos, macroClassLoader).withSpan(tree1.span)
511+
if (ctx.reporter.hasErrors) EmptyTree
512+
else evaluatedSplice
513+
case _ =>
514+
super.transform(tree1)
515+
}
516+
}.transform(expansion)
517+
}
518+
490519
/** A utility object offering methods for rewriting inlined code */
491520
object reducer {
492521

+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"))), "unary_~"), 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"))), "unary_~"), 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/gestalt-optional-staging/Test_2.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Port of https://github.com/liufengyun/gestalt/blob/master/macros/src/test/scala/gestalt/macros/OptionalTest.scala
1+
ge// Port of https://github.com/liufengyun/gestalt/blob/master/macros/src/test/scala/gestalt/macros/OptionalTest.scala
22

33
object Test {
44

tests/run/quote-whitebox.check

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
1
2+
a
+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/run/quote-whitebox/Test_2.scala

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import Macros._
2+
3+
object Test {
4+
def main(args: Array[String]): Unit = {
5+
val a: Int = defaultOf("int")
6+
val b: String = defaultOf("string")
7+
println(a)
8+
println(b)
9+
}
10+
}

0 commit comments

Comments
 (0)