Skip to content

Commit 340d06b

Browse files
Move inline trait inlining to its own phase
1 parent ae240e3 commit 340d06b

File tree

5 files changed

+136
-76
lines changed

5 files changed

+136
-76
lines changed

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

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class Compiler {
4848
/** Phases dealing with TASTY tree pickling and unpickling */
4949
protected def picklerPhases: List[List[Phase]] =
5050
List(new Pickler) :: // Generate TASTY info
51+
List(new SpecializeInlineTraits) :: // Inline the code of inline traits into their children
5152
List(new Inlining) :: // Inline and execute macros
5253
List(new PostInlining) :: // Add mirror support for inlined code
5354
List(new CheckUnused.PostInlining) :: // Check for unused elements

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ object Phases {
210210
private var myPostTyperPhase: Phase = _
211211
private var mySbtExtractDependenciesPhase: Phase = _
212212
private var myPicklerPhase: Phase = _
213+
private var mySpecializeInlineTraitsPhase: Phase = _
213214
private var myInliningPhase: Phase = _
214215
private var myStagingPhase: Phase = _
215216
private var mySplicingPhase: Phase = _
@@ -235,6 +236,7 @@ object Phases {
235236
final def postTyperPhase: Phase = myPostTyperPhase
236237
final def sbtExtractDependenciesPhase: Phase = mySbtExtractDependenciesPhase
237238
final def picklerPhase: Phase = myPicklerPhase
239+
final def specializeInlineTraitsPhase: Phase = mySpecializeInlineTraitsPhase
238240
final def inliningPhase: Phase = myInliningPhase
239241
final def stagingPhase: Phase = myStagingPhase
240242
final def splicingPhase: Phase = mySplicingPhase
@@ -263,6 +265,7 @@ object Phases {
263265
myPostTyperPhase = phaseOfClass(classOf[PostTyper])
264266
mySbtExtractDependenciesPhase = phaseOfClass(classOf[sbt.ExtractDependencies])
265267
myPicklerPhase = phaseOfClass(classOf[Pickler])
268+
mySpecializeInlineTraitsPhase = phaseOfClass(classOf[SpecializeInlineTraits])
266269
myInliningPhase = phaseOfClass(classOf[Inlining])
267270
myStagingPhase = phaseOfClass(classOf[Staging])
268271
mySplicingPhase = phaseOfClass(classOf[Splicing])
@@ -451,8 +454,9 @@ object Phases {
451454
def postTyperPhase(using Context): Phase = ctx.base.postTyperPhase
452455
def sbtExtractDependenciesPhase(using Context): Phase = ctx.base.sbtExtractDependenciesPhase
453456
def picklerPhase(using Context): Phase = ctx.base.picklerPhase
457+
def specializeInlineTraitsPhase(using Context): Phase = ctx.base.specializeInlineTraitsPhase
454458
def inliningPhase(using Context): Phase = ctx.base.inliningPhase
455-
def stagingPhase(using Context): Phase = ctx.base.stagingPhase
459+
def stagingPhase(using Context): Phase = ctx.base.stagingPhase
456460
def splicingPhase(using Context): Phase = ctx.base.splicingPhase
457461
def firstTransformPhase(using Context): Phase = ctx.base.firstTransformPhase
458462
def refchecksPhase(using Context): Phase = ctx.base.refchecksPhase

compiler/src/dotty/tools/dotc/inlines/Inlines.scala

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ object Inlines:
7272
&& (
7373
ctx.phase == Phases.inliningPhase
7474
|| (ctx.phase == Phases.typerPhase && needsTransparentInlining(tree))
75+
|| ctx.phase == Phases.specializeInlineTraitsPhase
7576
)
7677
&& !ctx.typer.hasInliningErrors
7778
&& !ctx.base.stopInlining

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

+1-75
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,12 @@ import dotty.tools.dotc.ast.Trees._
1111
import dotty.tools.dotc.quoted._
1212
import dotty.tools.dotc.inlines.Inlines
1313
import dotty.tools.dotc.ast.TreeMapWithImplicits
14-
import dotty.tools.dotc.core.DenotTransformers.SymTransformer
1514
import dotty.tools.dotc.staging.StagingLevel
16-
import dotty.tools.dotc.core.SymDenotations.SymDenotation
17-
import dotty.tools.dotc.core.StdNames.str
18-
import dotty.tools.dotc.core.Types.*
19-
import dotty.tools.dotc.core.Names.Name
2015

2116
import scala.collection.mutable.ListBuffer
2217

2318
/** Inlines all calls to inline methods that are not in an inline method or a quote */
24-
class Inlining extends MacroTransform, SymTransformer {
19+
class Inlining extends MacroTransform {
2520

2621
import tpd._
2722

@@ -62,56 +57,6 @@ class Inlining extends MacroTransform, SymTransformer {
6257
new InliningTreeMap().transform(tree)
6358
}
6459

65-
override def transformSym(symd: SymDenotation)(using Context): SymDenotation =
66-
if symd.isClass && symd.owner.isInlineTrait && !symd.is(Module) then
67-
symd.copySymDenotation(name = newInnerClassName(symd.name), initFlags = (symd.flags &~ Final) | Trait)
68-
else
69-
symd
70-
71-
def transformInlineTrait(inlineTrait: TypeDef)(using Context): TypeDef =
72-
val tpd.TypeDef(_, tmpl: Template) = inlineTrait: @unchecked
73-
val body1 = tmpl.body.flatMap {
74-
case innerClass: TypeDef if innerClass.symbol.isClass =>
75-
val newTrait = makeTraitFromInnerClass(innerClass)
76-
val newType = makeTypeFromInnerClass(inlineTrait.symbol, innerClass, newTrait.symbol)
77-
List(newTrait, newType)
78-
case member: MemberDef =>
79-
List(member)
80-
case _ =>
81-
// Remove non-memberdefs, as they are normally placed into $init()
82-
Nil
83-
}
84-
val tmpl1 = cpy.Template(tmpl)(body = body1)
85-
cpy.TypeDef(inlineTrait)(rhs = tmpl1)
86-
87-
private def makeTraitFromInnerClass(innerClass: TypeDef)(using Context): TypeDef =
88-
val TypeDef(name, tmpl: Template) = innerClass: @unchecked
89-
val newInnerParents = tmpl.parents.mapConserve(ConcreteParentStripper.apply)
90-
val tmpl1 = cpy.Template(tmpl)(parents = newInnerParents) // TODO .withType(???)
91-
val newTrait = cpy.TypeDef(innerClass)(name = newInnerClassName(name), rhs = tmpl1)
92-
newTrait.symbol.setFlag(Synthetic)
93-
newTrait
94-
end makeTraitFromInnerClass
95-
96-
private def makeTypeFromInnerClass(parentSym: Symbol, innerClass: TypeDef, newTraitSym: Symbol)(using Context): TypeDef =
97-
val upperBound = innerClass.symbol.primaryConstructor.info match {
98-
case _: MethodType =>
99-
newTraitSym.typeRef
100-
case poly: PolyType =>
101-
HKTypeLambda(poly.paramNames)(tl => poly.paramInfos, tl => newTraitSym.typeRef.appliedTo(tl.paramRefs.head))
102-
}
103-
val newTypeSym = newSymbol(
104-
owner = parentSym,
105-
name = newTraitSym.name.asTypeName,
106-
flags = innerClass.symbol.flags & (Private | Protected) | Synthetic,
107-
info = TypeBounds.upper(upperBound),
108-
privateWithin = innerClass.symbol.privateWithin,
109-
coord = innerClass.symbol.coord,
110-
nestingLevel = innerClass.symbol.nestingLevel,
111-
).asType
112-
TypeDef(newTypeSym)
113-
end makeTypeFromInnerClass
114-
11560
private class InliningTreeMap extends TreeMapWithImplicits {
11661

11762
/** List of top level classes added by macro annotation in a package object.
@@ -121,13 +66,6 @@ class Inlining extends MacroTransform, SymTransformer {
12166

12267
override def transform(tree: Tree)(using Context): Tree = {
12368
tree match
124-
case tree: TypeDef if tree.symbol.isInlineTrait =>
125-
transformInlineTrait(tree)
126-
case tree: TypeDef if Inlines.needsInlining(tree) =>
127-
val tree1 = super.transform(tree).asInstanceOf[TypeDef]
128-
if tree1.tpe.isError then tree1
129-
else if tree1.symbol.isInlineTrait then transformInlineTrait(tree1)
130-
else Inlines.inlineParentInlineTraits(tree1)
13169
case tree: MemberDef =>
13270
if tree.symbol.is(Inline) then tree
13371
else if tree.symbol.is(Param) then super.transform(tree)
@@ -169,18 +107,6 @@ class Inlining extends MacroTransform, SymTransformer {
169107
else super.transform(tree)
170108
}
171109
}
172-
173-
private def newInnerClassName(name: Name): name.ThisName = name ++ str.INLINE_TRAIT_INNER_CLASS_SUFFIX
174-
175-
private object ConcreteParentStripper extends TreeAccumulator[Tree] {
176-
def apply(tree: Tree)(using Context): Tree = apply(tree, tree)
177-
178-
override def apply(x: Tree, tree: Tree)(using Context): Tree = tree match {
179-
case ident: Ident => ident
180-
case tpt: TypeTree => tpt
181-
case _ => foldOver(x, tree)
182-
}
183-
}
184110
}
185111

186112
object Inlining:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import core._
5+
import Flags._
6+
import Contexts._
7+
import Symbols._
8+
import SymUtils._
9+
import dotty.tools.dotc.ast.tpd
10+
import dotty.tools.dotc.ast.Trees._
11+
import dotty.tools.dotc.quoted._
12+
import dotty.tools.dotc.inlines.Inlines
13+
import dotty.tools.dotc.ast.TreeMapWithImplicits
14+
import dotty.tools.dotc.core.DenotTransformers.SymTransformer
15+
import dotty.tools.dotc.staging.StagingLevel
16+
import dotty.tools.dotc.core.SymDenotations.SymDenotation
17+
import dotty.tools.dotc.core.StdNames.{str, nme}
18+
import dotty.tools.dotc.core.Types.*
19+
import dotty.tools.dotc.core.Names.{Name, TermName}
20+
21+
import scala.collection.mutable.ListBuffer
22+
23+
class SpecializeInlineTraits extends MacroTransform, SymTransformer {
24+
25+
import tpd._
26+
27+
override def phaseName: String = SpecializeInlineTraits.name
28+
29+
override def description: String = SpecializeInlineTraits.description
30+
31+
override def changesMembers: Boolean = true
32+
33+
override def changesParents: Boolean = true
34+
35+
override def run(using Context): Unit =
36+
try super.run
37+
catch case _: CompilationUnit.SuspendException => ()
38+
39+
override def newTransformer(using Context): Transformer = new Transformer {
40+
override def transform(tree: Tree)(using Context): Tree = tree match {
41+
case tree: TypeDef if tree.symbol.isInlineTrait =>
42+
transformInlineTrait(tree)
43+
case tree: TypeDef if Inlines.needsInlining(tree) =>
44+
val tree1 = super.transform(tree).asInstanceOf[TypeDef]
45+
if tree1.tpe.isError then tree1
46+
else if tree1.symbol.isInlineTrait then transformInlineTrait(tree1)
47+
else Inlines.inlineParentInlineTraits(tree1)
48+
case _ => super.transform(tree)
49+
}
50+
}
51+
52+
override def transformSym(symd: SymDenotation)(using Context): SymDenotation =
53+
if symd.isClass && symd.owner.isInlineTrait && !symd.is(Module) then
54+
symd.copySymDenotation(name = SpecializeInlineTraits.newInnerClassName(symd.name), initFlags = (symd.flags &~ Final) | Trait)
55+
else
56+
symd
57+
58+
override def checkPostCondition(tree: Tree)(using Context): Unit =
59+
tree match {
60+
// TODO
61+
case _ =>
62+
}
63+
64+
extension (tree: Tree)
65+
private def hasSpecializedVersion: Boolean =
66+
false
67+
68+
private def transformInlineTrait(inlineTrait: TypeDef)(using Context): TypeDef =
69+
val tpd.TypeDef(_, tmpl: Template) = inlineTrait: @unchecked
70+
val body1 = tmpl.body.flatMap {
71+
case innerClass: TypeDef if innerClass.symbol.isClass =>
72+
val newTrait = makeTraitFromInnerClass(innerClass)
73+
val newType = makeTypeFromInnerClass(inlineTrait.symbol, innerClass, newTrait.symbol)
74+
List(newTrait, newType)
75+
case member: MemberDef =>
76+
List(member)
77+
case _ =>
78+
// Remove non-memberdefs, as they are normally placed into $init()
79+
Nil
80+
}
81+
val tmpl1 = cpy.Template(tmpl)(body = body1)
82+
cpy.TypeDef(inlineTrait)(rhs = tmpl1)
83+
end transformInlineTrait
84+
85+
private def makeTraitFromInnerClass(innerClass: TypeDef)(using Context): TypeDef =
86+
val TypeDef(name, tmpl: Template) = innerClass: @unchecked
87+
val newInnerParents = tmpl.parents.mapConserve(ConcreteParentStripper.apply)
88+
val tmpl1 = cpy.Template(tmpl)(parents = newInnerParents) // TODO .withType(???)
89+
val newTrait = cpy.TypeDef(innerClass)(name = SpecializeInlineTraits.newInnerClassName(name), rhs = tmpl1)
90+
newTrait.symbol.setFlag(Synthetic)
91+
newTrait
92+
end makeTraitFromInnerClass
93+
94+
private def makeTypeFromInnerClass(parentSym: Symbol, innerClass: TypeDef, newTraitSym: Symbol)(using Context): TypeDef =
95+
val upperBound = innerClass.symbol.primaryConstructor.info match {
96+
case _: MethodType =>
97+
newTraitSym.typeRef
98+
case poly: PolyType =>
99+
HKTypeLambda(poly.paramNames)(tl => poly.paramInfos, tl => newTraitSym.typeRef.appliedTo(tl.paramRefs.head))
100+
}
101+
val newTypeSym = newSymbol(
102+
owner = parentSym,
103+
name = newTraitSym.name.asTypeName,
104+
flags = innerClass.symbol.flags & (Private | Protected) | Synthetic,
105+
info = TypeBounds.upper(upperBound),
106+
privateWithin = innerClass.symbol.privateWithin,
107+
coord = innerClass.symbol.coord,
108+
nestingLevel = innerClass.symbol.nestingLevel,
109+
).asType
110+
TypeDef(newTypeSym)
111+
end makeTypeFromInnerClass
112+
113+
private object ConcreteParentStripper extends TreeAccumulator[Tree] {
114+
def apply(tree: Tree)(using Context): Tree = apply(tree, tree)
115+
116+
override def apply(x: Tree, tree: Tree)(using Context): Tree = tree match {
117+
case ident: Ident => ident
118+
case tpt: TypeTree => tpt
119+
case _ => foldOver(x, tree)
120+
}
121+
}
122+
}
123+
124+
object SpecializeInlineTraits:
125+
val name: String = "specializeInlineTraits"
126+
val description: String = "inline the code of inline traits and specialize calls to their members"
127+
128+
private[transform] def newInnerClassName(name: Name): name.ThisName = name ++ str.INLINE_TRAIT_INNER_CLASS_SUFFIX

0 commit comments

Comments
 (0)