Skip to content

Commit 0c61b36

Browse files
committed
Inline non-transparent calls after Pickler
1 parent c372fa1 commit 0c61b36

File tree

15 files changed

+152
-6
lines changed

15 files changed

+152
-6
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class Compiler {
5050
/** Phases dealing with TASTY tree pickling and unpickling */
5151
protected def picklerPhases: List[List[Phase]] =
5252
List(new Pickler) :: // Generate TASTY info
53+
List(new Inlining) :: // Inline and execute macros
5354
List(new PickleQuotes) :: // Turn quoted trees into explicit run-time data structures
5455
Nil
5556

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ class ScalaSettings extends Settings.SettingGroup {
186186
val Yinstrument: Setting[Boolean] = BooleanSetting("-Yinstrument", "Add instrumentation code that counts allocations and closure creations.")
187187
val YinstrumentDefs: Setting[Boolean] = BooleanSetting("-Yinstrument-defs", "Add instrumentation code that counts method calls; needs -Yinstrument to be set, too.")
188188

189+
// TODO Remove. Added to help bootstrappting this change.
190+
val YinlineBlackboxAfterTyper: Setting[Boolean] = BooleanSetting("-Yinline-blackbox-after-typer", "")
191+
189192
/** Dottydoc specific settings */
190193
val siteRoot: Setting[String] = StringSetting(
191194
"-siteroot",
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import core._
5+
import Decorators._
6+
import Flags._
7+
import Types._
8+
import Contexts._
9+
import Symbols._
10+
import Constants._
11+
import ast.Trees._
12+
import ast.{TreeTypeMap, untpd}
13+
import util.Spans._
14+
import tasty.TreePickler.Hole
15+
import SymUtils._
16+
import NameKinds._
17+
import dotty.tools.dotc.ast.tpd
18+
import typer.Implicits.SearchFailureType
19+
20+
import scala.collection.mutable
21+
import dotty.tools.dotc.core.Annotations._
22+
import dotty.tools.dotc.core.Names._
23+
import dotty.tools.dotc.core.StdNames._
24+
import dotty.tools.dotc.quoted._
25+
import dotty.tools.dotc.transform.TreeMapWithStages._
26+
import dotty.tools.dotc.typer.Inliner
27+
28+
import scala.annotation.constructorOnly
29+
30+
class Inlining extends MacroTransform {
31+
import tpd._
32+
33+
override def phaseName: String = Inlining.name
34+
35+
override def allowsImplicitSearch: Boolean = true
36+
37+
override def run(using Context): Unit =
38+
// if (ctx.settings.YinlineBlackboxAfterTyper.value)
39+
super.run
40+
41+
override def checkPostCondition(tree: Tree)(using Context): Unit =
42+
tree match {
43+
case tree: RefTree if !Inliner.inInlineMethod =>
44+
assert(!tree.symbol.isInlineMethod)
45+
case _ =>
46+
}
47+
48+
protected def newTransformer(using Context): Transformer = new Transformer {
49+
override def transform(tree: tpd.Tree)(using Context): tpd.Tree =
50+
tree match
51+
case tree: DefTree =>
52+
if tree.symbol.is(Inline) then tree
53+
else super.transform(tree)
54+
case _: Typed | _: Block =>
55+
super.transform(tree)
56+
case _ if Inliner.isInlineable(tree) && !tree.tpe.widen.isInstanceOf[MethodOrPoly] =>
57+
val tree1 = super.transform(tree)
58+
val inlined = Inliner.inlineCall(tree1)
59+
if tree1 eq inlined then inlined
60+
else transform(inlined)
61+
case _ =>
62+
super.transform(tree)
63+
64+
}
65+
}
66+
67+
object Inlining {
68+
val name: String = "inlining"
69+
}
70+
71+
// inlined class definition
72+
// tests/pos/i7068-a.scala failed
73+
// tests/pos/i7068-b.scala failed
74+
75+
// tulpe xxl: deep subtypes
76+
// tests/pos/i7580.scala failed
77+
78+
// inlined inline match proxy failing
79+
// tests/pos/i8892.scala failed
80+
81+
// inlined inline val not pure
82+
// tests/pos/i8843.scala failed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ object Inliner {
4343
* @pre hasBodyToInline(sym)
4444
*/
4545
def bodyToInline(sym: SymDenotation)(using Context): Tree =
46-
if (sym.isInlineMethod && sym.hasAnnotation(defn.BodyAnnot))
46+
if hasBodyToInline(sym) then
4747
sym.getAnnotation(defn.BodyAnnot).get.tree
4848
else
4949
EmptyTree
@@ -62,6 +62,10 @@ object Inliner {
6262
case _ => isInlineable(tree.symbol) && !tree.tpe.isInstanceOf[MethodOrPoly]
6363
}
6464

65+
/** `sym` is an inline method with a known body to inline which looks like a tansparent inline */
66+
def hasTransparentBody(sym: SymDenotation)(using Context): Boolean =
67+
sym.exists && !bodyToInline(sym).isInstanceOf[Typed] // may have false negatives
68+
6569
/** Try to inline a call to an inline method. Fail with error if the maximal
6670
* inline depth is exceeded.
6771
*

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3272,6 +3272,7 @@ class Typer extends Namer
32723272
else if (methPart(tree).symbol.isAllOf(Inline | Deferred) && !Inliner.inInlineMethod) then
32733273
errorTree(tree, i"Deferred inline ${methPart(tree).symbol.showLocated} cannot be invoked")
32743274
else if (Inliner.isInlineable(tree) &&
3275+
(!ctx.settings.YinlineBlackboxAfterTyper.value || Inliner.hasTransparentBody(tree.symbol)) &&
32753276
!ctx.settings.YnoInline.value &&
32763277
!suppressInline) {
32773278
tree.tpe <:< wildApprox(pt)
@@ -3614,7 +3615,7 @@ class Typer extends Namer
36143615
}
36153616

36163617
// Overridden in InlineTyper
3617-
def suppressInline(using Context): Boolean = ctx.isAfterTyper
3618+
def suppressInline(using Context): Boolean = ctx.isAfterTyper && ctx.phase.phaseName != "inlining"
36183619

36193620
/** Does the "contextuality" of the method type `methType` match the one of the prototype `pt`?
36203621
* This is the case if

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class CompilationTests {
3939
compileFilesInDir("tests/new", defaultOptions),
4040
compileFilesInDir("tests/pos-scala2", scala2CompatMode),
4141
compileFilesInDir("tests/pos-custom-args/erased", defaultOptions.and("-Yerased-terms")),
42-
compileFilesInDir("tests/pos", defaultOptions),
42+
compileFilesInDir("tests/pos", defaultOptions /*and "-Yinline-blackbox-after-typer"*/),
4343
compileFilesInDir("tests/pos-deep-subtype", allowDeepSubtypes),
4444
compileFile(
4545
// succeeds despite -Xfatal-warnings because of -nowarn

library/src/scala/compiletime/package.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ package object compiletime {
141141
* @tparam T the tuple containing the types of the values to be summoned
142142
* @return the given values typed as elements of the tuple
143143
*/
144-
inline def summonAll[T <: Tuple]: Widen[T] =
144+
// FIXME: missing span in tests/run/summonAll.scala
145+
/*transparent */inline def summonAll[T <: Tuple]: Widen[T] =
145146
val res =
146147
inline erasedValue[T] match
147148
case _: EmptyTuple => EmptyTuple

tests/neg-macros/i9014/Macros_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
import scala.quoted._
22
trait Bar
3-
inline given Bar = ${ impl }
3+
transparent inline given Bar = ${ impl }
44
def impl(using Quotes): Expr[Bar] = quotes.reflect.report.throwError("Failed to expand!")

tests/neg-macros/i9014b.check

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
-- Error: tests/neg-macros/i9014b/Test_2.scala:1:23 --------------------------------------------------------------------
3+
1 |val tests = summon[Bar] // error
4+
| ^
5+
| no implicit argument of type Bar was found for parameter x of method summon in object Predef.
6+
| I found:
7+
|
8+
| given_Bar
9+
|
10+
| But method given_Bar does not match type Bar.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import scala.quoted._
2+
trait Bar
3+
inline given Bar = ${ impl }
4+
def impl(using Quotes): Expr[Bar] = quotes.reflect.report.throwError("Failed to expand!")

tests/neg-macros/i9014b/Test_2.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
val tests = summon[Bar] // error

tests/run-macros/no-symbol/2.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
object Test {
22
def main(args: Array[String]): Unit = {
33
assert(Macro.foo[Foo] == "symbol")
4-
assert(Macro.foo[Box] == "no symbol")
4+
assert(Macro.foo[Box[_]] == "no symbol")
55
}
66
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import scala.quoted._
2+
3+
object Macros {
4+
5+
inline def blackbox: Int = ${one}
6+
7+
transparent inline def whitebox: Int = ${one}
8+
9+
private def one(using Quotes): Expr[Int] = Expr(1)
10+
11+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import scala.quoted._
2+
import Macros._
3+
4+
object Test {
5+
def main(args: Array[String]): Unit = {
6+
val a: Int = blackbox
7+
val b: 1 = whitebox
8+
9+
assert(a == 1)
10+
assert(b == 1)
11+
}
12+
}

tests/run/whitebox-inline.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import scala.quoted._
2+
3+
object Test {
4+
def main(args: Array[String]): Unit = {
5+
val a: Int = blackbox
6+
val b: 1 = whitebox
7+
8+
assert(a == 1)
9+
assert(b == 1)
10+
}
11+
12+
inline def blackbox: Int = 1
13+
14+
transparent inline def whitebox: Int = 1
15+
16+
}

0 commit comments

Comments
 (0)