Skip to content

Commit 9a992f0

Browse files
Merge pull request #5383 from dotty-staging/add-specializing-inline
Add specializing inline
2 parents 40c714b + 221d337 commit 9a992f0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+339
-291
lines changed

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@ package dotc
33

44
import util.SourceFile
55
import ast.{tpd, untpd}
6-
import dotty.tools.dotc.ast.Trees
76
import tpd.{Tree, TreeTraverser}
87
import typer.PrepareInlineable.InlineAccessors
98
import dotty.tools.dotc.core.Contexts.Context
109
import dotty.tools.dotc.core.SymDenotations.ClassDenotation
1110
import dotty.tools.dotc.core.Symbols._
1211
import dotty.tools.dotc.transform.SymUtils._
13-
import dotty.tools.dotc.typer.Inliner
1412

1513
class CompilationUnit(val source: SourceFile) {
1614

@@ -25,8 +23,8 @@ class CompilationUnit(val source: SourceFile) {
2523
/** Pickled TASTY binaries, indexed by class. */
2624
var pickled: Map[ClassSymbol, Array[Byte]] = Map()
2725

28-
/** Will be set to `true` if contains `Quote`, `Splice` or calls to inline methods.
29-
* The information is used in phase `Staging` in order to avoid traversing a quote-less tree.
26+
/** Will be set to `true` if contains `Quote`.
27+
* The information is used in phase `Staging` in order to avoid traversing trees that need no transformations.
3028
*/
3129
var needsStaging: Boolean = false
3230

@@ -57,8 +55,7 @@ object CompilationUnit {
5755
private class Force extends TreeTraverser {
5856
var needsStaging = false
5957
def traverse(tree: Tree)(implicit ctx: Context): Unit = {
60-
// Note that top-level splices are still inside the inline methods
61-
if (tree.symbol.isQuote || tpd.isInlineCall(tree))
58+
if (tree.symbol.isQuote)
6259
needsStaging = true
6360
traverseChildren(tree)
6461
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ 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 Staging) :: // Inline calls, expand macros and turn quoted trees into explicit run-time data structures
47+
List(new Staging) :: // Expand macros and turn quoted trees into explicit run-time data structures
4848
Nil
4949

5050
/** Phases dealing with the transformation from pickled trees to backend trees */

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,19 +157,31 @@ object desugar {
157157
ValDef(epname, tpt, EmptyTree).withFlags(paramFlags | Implicit)
158158
}
159159

160-
/** Expand context bounds to evidence params. E.g.,
160+
/** 1. Expand context bounds to evidence params. E.g.,
161161
*
162162
* def f[T >: L <: H : B](params)
163163
* ==>
164164
* def f[T >: L <: H](params)(implicit evidence$0: B[T])
165165
*
166-
* Expand default arguments to default getters. E.g,
166+
* 2. Expand default arguments to default getters. E.g,
167167
*
168168
* def f[T: B](x: Int = 1)(y: String = x + "m") = ...
169169
* ==>
170170
* def f[T](x: Int)(y: String)(implicit evidence$0: B[T]) = ...
171171
* def f$default$1[T] = 1
172172
* def f$default$2[T](x: Int) = x + "m"
173+
*
174+
* 3. Convert <: T to : T in specializing inline methods. E.g.
175+
*
176+
* inline def f(x: Boolean) <: Any = if (x) 1 else ""
177+
* ==>
178+
* inline def f(x: Boolean): Any = if (x) 1 else ""
179+
*
180+
* 4. Upcast non-specializing inline methods. E.g.
181+
*
182+
* inline def f(x: Boolean): Any = if (x) 1 else ""
183+
* ==>
184+
* inline def f(x: Boolean): Any = (if (x) 1 else ""): Any
173185
*/
174186
private def defDef(meth: DefDef, isPrimaryConstructor: Boolean = false)(implicit ctx: Context): Tree = {
175187
val DefDef(name, tparams, vparamss, tpt, rhs) = meth
@@ -188,7 +200,16 @@ object desugar {
188200
cpy.TypeDef(tparam)(rhs = desugarContextBounds(tparam.rhs))
189201
}
190202

191-
val meth1 = addEvidenceParams(cpy.DefDef(meth)(tparams = tparams1), epbuf.toList)
203+
var meth1 = addEvidenceParams(cpy.DefDef(meth)(tparams = tparams1), epbuf.toList)
204+
205+
if (meth1.mods.is(Inline))
206+
meth1.tpt match {
207+
case TypeBoundsTree(_, tpt1) =>
208+
meth1 = cpy.DefDef(meth1)(tpt = tpt1)
209+
case tpt if !tpt.isEmpty && !meth1.rhs.isEmpty =>
210+
meth1 = cpy.DefDef(meth1)(rhs = Typed(meth1.rhs, tpt))
211+
case _ =>
212+
}
192213

193214
/** The longest prefix of parameter lists in vparamss whose total length does not exceed `n` */
194215
def takeUpTo(vparamss: List[List[ValDef]], n: Int): List[List[ValDef]] = vparamss match {

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ package ast
55
import core._
66
import Flags._, Trees._, Types._, Contexts._
77
import Names._, StdNames._, NameOps._, Symbols._
8-
import typer.{ConstFold, Inliner}
8+
import typer.ConstFold
99
import reporting.trace
1010

1111
import scala.annotation.tailrec
@@ -770,14 +770,6 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
770770
false
771771
}
772772

773-
/** Is this call a call to a method that is marked as Inline */
774-
def isInlineCall(arg: Tree)(implicit ctx: Context): Boolean = arg match {
775-
case _: RefTree | _: GenericApply[_] =>
776-
!arg.tpe.widenDealias.isInstanceOf[MethodicType] && Inliner.isInlineable(arg)
777-
case _ =>
778-
false
779-
}
780-
781773
/** Structural tree comparison (since == on trees is reference equality).
782774
* For the moment, only Ident, Select, Literal, Apply and TypeApply are supported
783775
*/

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -585,8 +585,9 @@ object Trees {
585585

586586
/** A tree representing inlined code.
587587
*
588-
* @param call Info about the original call that was inlined.
589-
* Only a reference to the toplevel class from which the call was inlined.
588+
* @param call Info about the original call that was inlined
589+
* Until PostTyper, this is the full call, afterwards only
590+
* a reference to the toplevel class from which the call was inlined.
590591
* @param bindings Bindings for proxies to be used in the inlined code
591592
* @param expansion The inlined tree, minus bindings.
592593
*

compiler/src/dotty/tools/dotc/core/NameOps.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ package core
44
import java.security.MessageDigest
55
import scala.io.Codec
66
import Names._, StdNames._, Contexts._, Symbols._, Flags._, NameKinds._, Types._
7-
import util.Chars
7+
import scala.tasty.util.Chars
88
import Chars.isOperatorPart
99
import Definitions._
1010

compiler/src/dotty/tools/dotc/core/Names.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import util.NameTransformer
77
import printing.{Showable, Texts, Printer}
88
import Texts.Text
99
import StdNames.str
10-
import util.Chars.isIdentifierStart
10+
import scala.tasty.util.Chars.isIdentifierStart
1111
import collection.immutable
1212
import config.Config
1313
import java.util.HashMap

compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala

Lines changed: 56 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ Standard-Section: "ASTs" TopLevelStat*
8686
TYPED Length expr_Term ascriptionType_Tern
8787
ASSIGN Length lhs_Term rhs_Term
8888
BLOCK Length expr_Term Stat*
89+
INLINED Length expr_Term call_Term? ValOrDefDef*
8990
LAMBDA Length meth_Term target_Type?
9091
IF Length cond_Term then_Term else_Term
9192
MATCH Length sel_Term CaseDef*
@@ -184,6 +185,7 @@ Standard-Section: "ASTs" TopLevelStat*
184185
OVERRIDE
185186
INLINE
186187
MACRO // inline method containing toplevel splices
188+
INLINEPROXY // symbol of binding representing an inline parameter
187189
STATIC // mapped to static Java member
188190
OBJECT // an object or its class
189191
TRAIT // a trait
@@ -233,7 +235,7 @@ Standard Section: "Comments" Comment*
233235
object TastyFormat {
234236

235237
final val header: Array[Int] = Array(0x5C, 0xA1, 0xAB, 0x1F)
236-
val MajorVersion: Int = 13
238+
val MajorVersion: Int = 11
237239
val MinorVersion: Int = 0
238240

239241
/** Tags used to serialize names */
@@ -286,25 +288,26 @@ object TastyFormat {
286288
final val IMPLICIT = 13
287289
final val LAZY = 14
288290
final val OVERRIDE = 15
289-
final val INLINE = 16
290-
final val STATIC = 17
291-
final val OBJECT = 18
292-
final val TRAIT = 19
293-
final val ENUM = 20
294-
final val LOCAL = 21
295-
final val SYNTHETIC = 22
296-
final val ARTIFACT = 23
297-
final val MUTABLE = 24
298-
final val FIELDaccessor = 25
299-
final val CASEaccessor = 26
300-
final val COVARIANT = 27
301-
final val CONTRAVARIANT = 28
302-
final val SCALA2X = 29
303-
final val DEFAULTparameterized = 30
304-
final val STABLE = 31
305-
final val MACRO = 32
306-
final val ERASED = 33
307-
final val PARAMsetter = 34
291+
final val INLINEPROXY = 16
292+
final val INLINE = 17
293+
final val STATIC = 18
294+
final val OBJECT = 19
295+
final val TRAIT = 20
296+
final val ENUM = 21
297+
final val LOCAL = 22
298+
final val SYNTHETIC = 23
299+
final val ARTIFACT = 24
300+
final val MUTABLE = 25
301+
final val FIELDaccessor = 26
302+
final val CASEaccessor = 27
303+
final val COVARIANT = 28
304+
final val CONTRAVARIANT = 29
305+
final val SCALA2X = 30
306+
final val DEFAULTparameterized = 31
307+
final val STABLE = 32
308+
final val MACRO = 33
309+
final val ERASED = 34
310+
final val PARAMsetter = 35
308311

309312
// Cat. 2: tag Nat
310313

@@ -378,35 +381,36 @@ object TastyFormat {
378381
final val RETURN = 144
379382
final val WHILE = 145
380383
final val TRY = 146
381-
final val SELECTouter = 147
382-
final val REPEATED = 148
383-
final val BIND = 149
384-
final val ALTERNATIVE = 150
385-
final val UNAPPLY = 151
386-
final val ANNOTATEDtype = 152
387-
final val ANNOTATEDtpt = 153
388-
final val CASEDEF = 154
389-
final val TEMPLATE = 155
390-
final val SUPER = 156
391-
final val SUPERtype = 157
392-
final val REFINEDtype = 158
393-
final val REFINEDtpt = 159
394-
final val APPLIEDtype = 160
395-
final val APPLIEDtpt = 161
396-
final val TYPEBOUNDS = 162
397-
final val TYPEBOUNDStpt = 163
398-
final val ANDtype = 164
399-
final val ANDtpt = 165
400-
final val ORtype = 166
401-
final val ORtpt = 167
402-
final val POLYtype = 168
403-
final val TYPELAMBDAtype = 169
404-
final val LAMBDAtpt = 170
405-
final val PARAMtype = 171
406-
final val ANNOTATION = 172
407-
final val TERMREFin = 173
408-
final val TYPEREFin = 174
409-
final val OBJECTDEF = 175
384+
final val INLINED = 147
385+
final val SELECTouter = 148
386+
final val REPEATED = 149
387+
final val BIND = 150
388+
final val ALTERNATIVE = 151
389+
final val UNAPPLY = 152
390+
final val ANNOTATEDtype = 153
391+
final val ANNOTATEDtpt = 154
392+
final val CASEDEF = 155
393+
final val TEMPLATE = 156
394+
final val SUPER = 157
395+
final val SUPERtype = 158
396+
final val REFINEDtype = 159
397+
final val REFINEDtpt = 160
398+
final val APPLIEDtype = 161
399+
final val APPLIEDtpt = 162
400+
final val TYPEBOUNDS = 163
401+
final val TYPEBOUNDStpt = 164
402+
final val ANDtype = 165
403+
final val ANDtpt = 166
404+
final val ORtype = 167
405+
final val ORtpt = 168
406+
final val POLYtype = 169
407+
final val TYPELAMBDAtype = 170
408+
final val LAMBDAtpt = 171
409+
final val PARAMtype = 172
410+
final val ANNOTATION = 173
411+
final val TERMREFin = 174
412+
final val TYPEREFin = 175
413+
final val OBJECTDEF = 176
410414

411415
// In binary: 101101EI
412416
// I = implicit method type
@@ -456,6 +460,7 @@ object TastyFormat {
456460
| LAZY
457461
| OVERRIDE
458462
| INLINE
463+
| INLINEPROXY
459464
| MACRO
460465
| STATIC
461466
| OBJECT
@@ -512,6 +517,7 @@ object TastyFormat {
512517
case LAZY => "LAZY"
513518
case OVERRIDE => "OVERRIDE"
514519
case INLINE => "INLINE"
520+
case INLINEPROXY => "INLINEPROXY"
515521
case MACRO => "MACRO"
516522
case STATIC => "STATIC"
517523
case OBJECT => "OBJECT"
@@ -579,6 +585,7 @@ object TastyFormat {
579585
case MATCH => "MATCH"
580586
case RETURN => "RETURN"
581587
case WHILE => "WHILE"
588+
case INLINED => "INLINED"
582589
case SELECTouter => "SELECTouter"
583590
case TRY => "TRY"
584591
case REPEATED => "REPEATED"

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,17 @@ class TreePickler(pickler: TastyPickler) {
442442
case SeqLiteral(elems, elemtpt) =>
443443
writeByte(REPEATED)
444444
withLength { pickleTree(elemtpt); elems.foreach(pickleTree) }
445+
case Inlined(call, bindings, expansion) =>
446+
writeByte(INLINED)
447+
bindings.foreach(preRegister)
448+
withLength {
449+
pickleTree(expansion)
450+
if (!call.isEmpty) pickleTree(call)
451+
bindings.foreach { b =>
452+
assert(b.isInstanceOf[DefDef] || b.isInstanceOf[ValDef])
453+
pickleTree(b)
454+
}
455+
}
445456
case Bind(name, body) =>
446457
registerDef(tree.symbol)
447458
writeByte(BIND)
@@ -608,6 +619,7 @@ class TreePickler(pickler: TastyPickler) {
608619
if (flags is Case) writeByte(CASE)
609620
if (flags is Override) writeByte(OVERRIDE)
610621
if (flags is Inline) writeByte(INLINE)
622+
if (flags is InlineProxy) writeByte(INLINEPROXY)
611623
if (flags is Macro) writeByte(MACRO)
612624
if (flags is JavaStatic) writeByte(STATIC)
613625
if (flags is Module) writeByte(OBJECT)

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ class TreeUnpickler(reader: TastyReader,
604604
case LAZY => addFlag(Lazy)
605605
case OVERRIDE => addFlag(Override)
606606
case INLINE => addFlag(Inline)
607+
case INLINEPROXY => addFlag(InlineProxy)
607608
case MACRO => addFlag(Macro)
608609
case STATIC => addFlag(JavaStatic)
609610
case OBJECT => addFlag(Module)
@@ -1072,6 +1073,17 @@ class TreeUnpickler(reader: TastyReader,
10721073
val stats = readStats(ctx.owner, end)
10731074
val expr = exprReader.readTerm()
10741075
Block(stats, expr)
1076+
case INLINED =>
1077+
val exprReader = fork
1078+
skipTree()
1079+
def maybeCall = nextUnsharedTag match {
1080+
case VALDEF | DEFDEF => EmptyTree
1081+
case _ => readTerm()
1082+
}
1083+
val call = ifBefore(end)(maybeCall, EmptyTree)
1084+
val bindings = readStats(ctx.owner, end).asInstanceOf[List[ValOrDefDef]]
1085+
val expansion = exprReader.readTerm() // need bindings in scope, so needs to be read before
1086+
Inlined(call, bindings, expansion)
10751087
case IF =>
10761088
If(readTerm(), readTerm(), readTerm())
10771089
case LAMBDA =>

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ class TASTYDecompiler extends TASTYCompiler {
1515
Nil
1616

1717
override protected def picklerPhases: List[List[Phase]] = Nil
18-
1918
override protected def transformPhases: List[List[Phase]] = Nil
2019

2120
override protected def backendPhases: List[List[Phase]] =

compiler/src/dotty/tools/dotc/parsing/CharArrayReader.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package dotty.tools
22
package dotc
33
package parsing
44

5-
import util.Chars._
5+
import scala.tasty.util.Chars._
66

77
abstract class CharArrayReader { self =>
88

compiler/src/dotty/tools/dotc/parsing/JavaScanners.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Scanners._
77
import util.SourceFile
88
import JavaTokens._
99
import scala.annotation.{ switch, tailrec }
10-
import util.Chars._
10+
import scala.tasty.util.Chars._
1111

1212
object JavaScanners {
1313

0 commit comments

Comments
 (0)