Skip to content

Commit 9dbe8b9

Browse files
committed
Move inlining inside Reify quotes
Split some neg tests as now only the first error is emitted.
1 parent 7067122 commit 9dbe8b9

File tree

14 files changed

+154
-64
lines changed

14 files changed

+154
-64
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ class Compiler {
4444
/** Phases dealing with TASTY tree pickling and unpickling */
4545
protected def picklerPhases: List[List[Phase]] =
4646
List(new Pickler) :: // Generate TASTY info
47-
List(new InlineCalls) :: // β-reduce inline calls
4847
List(new ReifyQuotes) :: // Turn quoted trees into explicit run-time data structures
4948
Nil
5049

compiler/src/dotty/tools/dotc/decompiler/TASTYDecompiler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package dotty.tools.dotc.decompiler
22

33
import dotty.tools.dotc.fromtasty._
44
import dotty.tools.dotc.core.Phases.Phase
5-
import dotty.tools.dotc.transform.InlineCalls
5+
import dotty.tools.dotc.transform.ReifyQuotes
66

77
/** Compiler from tasty to user readable high text representation
88
* of the compiled scala code.
@@ -16,7 +16,7 @@ class TASTYDecompiler extends TASTYCompiler {
1616
Nil
1717

1818
override protected def picklerPhases: List[List[Phase]] =
19-
List(new InlineCalls) :: // TODO should we really inline for the decompiler?
19+
List(new ReifyQuotes) :: // TODO should we really inline for the decompiler?
2020
Nil
2121

2222
override protected def transformPhases: List[List[Phase]] = Nil

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

Lines changed: 0 additions & 45 deletions
This file was deleted.

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

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ package dotty.tools.dotc
22
package transform
33

44
import core._
5-
import Decorators._, Flags._, Types._, Contexts._, Symbols._, Constants._
5+
import Decorators._
6+
import Flags._
7+
import Types._
8+
import Contexts._
9+
import Symbols._
10+
import Constants._
611
import ast.Trees._
712
import ast.{TreeTypeMap, untpd}
813
import util.Positions._
@@ -15,6 +20,7 @@ import typer.Implicits.SearchFailureType
1520
import scala.collection.mutable
1621
import dotty.tools.dotc.core.StdNames._
1722
import dotty.tools.dotc.core.quoted._
23+
import dotty.tools.dotc.typer.{ConstFold, Inliner}
1824
import dotty.tools.dotc.util.SourcePosition
1925

2026

@@ -60,7 +66,7 @@ import dotty.tools.dotc.util.SourcePosition
6066
* The Splicer is used to check that the RHS will be interpretable (with the `Splicer`) once inlined.
6167
*/
6268
class ReifyQuotes extends MacroTransformWithImplicits {
63-
import ast.tpd._
69+
import tpd._
6470
import ReifyQuotes._
6571

6672
/** Classloader used for loading macros */
@@ -88,7 +94,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
8894
}
8995

9096
override def run(implicit ctx: Context): Unit =
91-
if (ctx.compilationUnit.containsQuotesOrSplices) super.run
97+
if (ctx.compilationUnit.containsInlineCalls || ctx.compilationUnit.containsQuotesOrSplices) super.run
9298

9399
protected def newTransformer(implicit ctx: Context): Transformer =
94100
new Reifier(inQuote = false, null, 0, new LevelInfo, new Embedded, ctx)
@@ -437,7 +443,8 @@ class ReifyQuotes extends MacroTransformWithImplicits {
437443
else if (enclosingInlineds.nonEmpty) { // level 0 in an inlined call
438444
val spliceCtx = ctx.outer // drop the last `inlineContext`
439445
val pos: SourcePosition = Decorators.sourcePos(enclosingInlineds.head.pos)(spliceCtx)
440-
val evaluatedSplice = Splicer.splice(splice.qualifier, pos, macroClassLoader)(spliceCtx).withPos(splice.pos)
446+
val splicedTree = new InlineCalls().transform(splice.qualifier) // inline calls that where inlined at level -1
447+
val evaluatedSplice = Splicer.splice(splicedTree, pos, macroClassLoader)(spliceCtx).withPos(splice.pos)
441448
if (ctx.reporter.hasErrors) splice else transform(evaluatedSplice)
442449
}
443450
else if (!ctx.owner.isInlineMethod) { // level 0 outside an inline method
@@ -560,6 +567,9 @@ class ReifyQuotes extends MacroTransformWithImplicits {
560567
enteredSyms = enteredSyms.tail
561568
}
562569
tree match {
570+
case tree if isInlineCall(tree) && level == 0 && !ctx.reporter.hasErrors && !ctx.settings.YnoInline.value =>
571+
val tree2 = super.transform(tree) // transform arguments before inlining (inline arguments and constant fold arguments)
572+
transform(Inliner.inlineCall(tree2, tree.tpe.widen))
563573
case Quoted(quotedTree) =>
564574
quotation(quotedTree, tree)
565575
case tree: TypeTree if tree.tpe.typeSymbol.isSplice =>
@@ -610,7 +620,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
610620
}
611621
case _ =>
612622
markDef(tree)
613-
checkLevel(mapOverTree(enteredSyms))
623+
ConstFold(checkLevel(mapOverTree(enteredSyms)))
614624
}
615625
}
616626

@@ -635,6 +645,8 @@ class ReifyQuotes extends MacroTransformWithImplicits {
635645
}
636646

637647
object ReifyQuotes {
648+
import tpd._
649+
638650
val name: String = "reifyQuotes"
639651

640652
def toValue(tree: tpd.Tree): Option[Any] = tree match {
@@ -664,4 +676,20 @@ object ReifyQuotes {
664676
/** Get the list of embedded trees */
665677
def getTrees: List[tpd.Tree] = trees.toList
666678
}
679+
680+
/** β-reduce all calls to inline methods and preform constant folding */
681+
class InlineCalls extends TreeMap {
682+
override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
683+
case tree if isInlineCall(tree) && !ctx.reporter.hasErrors && !ctx.settings.YnoInline.value =>
684+
val tree2 = super.transform(tree) // transform arguments before inlining (inline arguments and constant fold arguments)
685+
transform(Inliner.inlineCall(tree2, tree.tpe.widen))
686+
case _: MemberDef =>
687+
val newTree = super.transform(tree)
688+
if (newTree.symbol.exists)
689+
newTree.symbol.defTree = newTree // set for inlined members
690+
newTree
691+
case _ =>
692+
ConstFold(super.transform(tree))
693+
}
694+
}
667695
}

tests/neg-with-compiler/quote-run-in-macro-2/quoted_2.scala

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,5 @@ import Macros._
22
object Test {
33
def main(args: Array[String]): Unit = {
44
println(foo(1)) // error
5-
println(foo(1 + 3)) // error
6-
val x = 3
7-
println(foo { // error
8-
val x = 5
9-
x
10-
})
115
}
126
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import scala.quoted._
2+
3+
import scala.quoted.Toolbox.Default._
4+
5+
object Macros {
6+
inline def foo(i: => Int): Int = ~fooImpl('(i))
7+
def fooImpl(i: Expr[Int]): Expr[Int] = {
8+
val y: Int = i.run
9+
y.toExpr
10+
}
11+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import Macros._
2+
object Test {
3+
def main(args: Array[String]): Unit = {
4+
println(foo(1 + 3)) // error
5+
}
6+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import scala.quoted._
2+
3+
import scala.quoted.Toolbox.Default._
4+
5+
object Macros {
6+
inline def foo(i: => Int): Int = ~fooImpl('(i))
7+
def fooImpl(i: Expr[Int]): Expr[Int] = {
8+
val y: Int = i.run
9+
y.toExpr
10+
}
11+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Macros._
2+
object Test {
3+
def main(args: Array[String]): Unit = {
4+
println(foo { // error
5+
val x = 5
6+
x
7+
})
8+
}
9+
}
Lines changed: 69 additions & 0 deletions
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 tasty: Tasty): Expr[Unit] = {
18+
import tasty._
19+
20+
val tree = cond.toTasty
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.toExpr[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+
}
Lines changed: 10 additions & 0 deletions
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(false !== "acb")
7+
macroAssert("acb" !== "acb") // error
8+
}
9+
10+
}

tests/neg/tasty-macro-assert/quoted_2.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ object Test {
55
def main(args: Array[String]): Unit = {
66
macroAssert(true === "cde")
77
macroAssert("acb" === "cde") // error
8-
macroAssert(false !== "acb")
9-
macroAssert("acb" !== "acb") // error
108
}
119

1210
}

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", TypeTree.Applied(TypeTree.Ident("Array"), List(TypeTree.Ident("String"))), None))), TypeTree.Ident("Unit"), Some(Term.Block(Nil, Term.Inlined(Some(TypeTree.Ident("Macros$")), Nil, Term.Select(Term.Apply(Term.Apply(Term.TypeApply(Term.Ident("impl"), List(TypeTree.Synthetic())), List(Term.Apply(Term.TypeApply(Term.Ident("apply"), List(TypeTree.Synthetic())), List(Term.Inlined(None, Nil, Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Synthetic(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Synthetic())))), ValDef("foo2", TypeTree.Synthetic(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Synthetic())))), ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Synthetic(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Synthetic()), "<init>", Some(Signature(Nil, java.lang.Object))), Nil)), None, List(TypeDef("B", TypeTree.Ident("Int")), DefDef("b", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit()))))))), List(Term.Ident("macroContext"))), "unary_~", Some(Signature(Nil, java.lang.Object)))))))
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.Apply(Term.TypeApply(Term.Ident("printOwners"), List(TypeTree.Synthetic())), List(Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Synthetic(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Synthetic())))), ValDef("foo2", TypeTree.Synthetic(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Synthetic())))), ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Synthetic(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Synthetic()), "<init>", Some(Signature(Nil, java.lang.Object))), Nil)), None, List(TypeDef("B", TypeTree.Ident("Int")), DefDef("b", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit())))))))
33

44
bar
55
DefDef("foo", Nil, Nil, TypeTree.Synthetic(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Synthetic()))))
@@ -8,7 +8,7 @@ bar2
88
DefDef("foo", Nil, Nil, TypeTree.Synthetic(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Synthetic()))))
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(TypeTree.Ident("Macros$")), Nil, Term.Select(Term.Apply(Term.Apply(Term.TypeApply(Term.Ident("impl"), List(TypeTree.Synthetic())), List(Term.Apply(Term.TypeApply(Term.Ident("apply"), List(TypeTree.Synthetic())), List(Term.Inlined(None, Nil, Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Synthetic(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Synthetic())))), ValDef("foo2", TypeTree.Synthetic(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Synthetic())))), ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Synthetic(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Synthetic()), "<init>", Some(Signature(Nil, java.lang.Object))), Nil)), None, List(TypeDef("B", TypeTree.Ident("Int")), DefDef("b", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit()))))))), List(Term.Ident("macroContext"))), "unary_~", Some(Signature(Nil, java.lang.Object)))))))
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.Apply(Term.TypeApply(Term.Ident("printOwners"), List(TypeTree.Synthetic())), List(Term.Block(List(DefDef("foo", Nil, Nil, TypeTree.Synthetic(), Some(Term.Block(List(DefDef("bar", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(1)))), ValDef("bar2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(2))))), Term.Typed(Term.Ident("bar"), TypeTree.Synthetic())))), ValDef("foo2", TypeTree.Synthetic(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Synthetic())))), ClassDef("A", DefDef("<init>", Nil, List(Nil), TypeTree.Synthetic(), None), List(Term.Apply(Term.Select(Term.New(TypeTree.Synthetic()), "<init>", Some(Signature(Nil, java.lang.Object))), Nil)), None, List(TypeDef("B", TypeTree.Ident("Int")), DefDef("b", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(5)))), ValDef("b2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(6))))))), Term.Literal(Constant.Unit())))))))
1212

1313
baz
1414
ValDef("foo2", TypeTree.Synthetic(), Some(Term.Block(List(DefDef("baz", Nil, Nil, TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(3)))), ValDef("baz2", TypeTree.Synthetic(), Some(Term.Literal(Constant.Int(4))))), Term.Typed(Term.Ident("baz"), TypeTree.Synthetic()))))

tests/run-with-compiler/i3876-d.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
6
22
{
33
val x$1: scala.Int = 3
4-
x$1.+(x$1)
4+
Test.inlineLambda.apply(x$1)
55
}

0 commit comments

Comments
 (0)