Skip to content

Commit cdeaa8d

Browse files
committed
Move inlining inside Reify quotes
1 parent 0832e02 commit cdeaa8d

File tree

10 files changed

+134
-57
lines changed

10 files changed

+134
-57
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
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package dotty.tools.dotc.transform
2+
3+
import dotty.tools.dotc.ast.Trees._
4+
import dotty.tools.dotc.ast.tpd
5+
import dotty.tools.dotc.core.Contexts._
6+
import dotty.tools.dotc.core.Types.MethodicType
7+
import dotty.tools.dotc.typer.{ConstFold, Inliner}
8+
9+
object InlineCall {
10+
import tpd._
11+
12+
/** Matches calls to inline methods */
13+
def unapply(arg: Tree)(implicit ctx: Context): Option[Tree] = arg match {
14+
case _: RefTree | _: GenericApply[_]
15+
if !arg.tpe.widenDealias.isInstanceOf[MethodicType] && Inliner.isInlineable(arg) =>
16+
Some(arg)
17+
case _ =>
18+
None
19+
}
20+
21+
/** β-reduce all calls to inline methods and preform constant folding */
22+
class Map extends TreeMap {
23+
override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
24+
case InlineCall(tree) if !ctx.reporter.hasErrors && !ctx.settings.YnoInline.value =>
25+
val tree2 = super.transform(tree) // transform arguments before inlining (inline arguments and constant fold arguments)
26+
transform(Inliner.inlineCall(tree2, tree.tpe.widen))
27+
case _: MemberDef =>
28+
val newTree = super.transform(tree)
29+
if (newTree.symbol.exists)
30+
newTree.symbol.defTree = newTree // set for inlined members
31+
newTree
32+
case _ =>
33+
ConstFold(super.transform(tree))
34+
}
35+
}
36+
}

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: 14 additions & 4 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

@@ -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 InlineCall.Map().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 InlineCall(tree) if 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

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)