Skip to content

Commit 21e65f1

Browse files
committed
Move inlining inside Reify quotes
Split some neg tests as now only the first error is emitted.
1 parent 86e5c12 commit 21e65f1

File tree

17 files changed

+158
-73
lines changed

17 files changed

+158
-73
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 & 4 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.
@@ -15,9 +15,7 @@ class TASTYDecompiler extends TASTYCompiler {
1515
List(new ReadTastyTreesFromClasses) :: // Load classes from tasty
1616
Nil
1717

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

2220
override protected def transformPhases: List[List[Phase]] = Nil
2321

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: 35 additions & 7 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,11 +20,12 @@ 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

21-
/** Translates quoted terms and types to `unpickle` method calls.
22-
* Checks that the phase consistency principle (PCP) holds.
27+
/** Inline calls to inline methods, evaluates macros, translates quoted terms (and types)
28+
* to `unpickle` method calls and checks that the phase consistency principle (PCP) holds.
2329
*
2430
*
2531
* Transforms top level quote
@@ -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
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
301301
private def registerType(tpe: Type): Unit = tpe match {
302302
case tpe: ThisType if !canElideThis(tpe) && !thisProxy.contains(tpe.cls) =>
303303
val proxyName = s"${tpe.cls.name}_this".toTermName
304-
val proxyType = inlineCallPrefix.tpe.tryNormalize match {
304+
val proxyType = inlineCallPrefix.tpe.dealias.tryNormalize match {
305305
case typeMatchResult if typeMatchResult.exists => typeMatchResult
306306
case _ => tpe.asSeenFrom(inlineCallPrefix.tpe, inlinedMethod.owner).widenIfUnstable
307307
}

compiler/test/dotc/pos-recompilation.whitelist

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,6 @@ t8132
985985
t8177d
986986
t8177e
987987
t8177h
988-
t8207
989988
t8219
990989
t8230a
991990
t8237

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+
}

0 commit comments

Comments
 (0)