Skip to content

Commit ebf32a2

Browse files
committed
Refactor TreeTypeMap
Break out an `InlinerMap` that contains inliner-specific overrides. This avoids a global mode in TreeTypeMap that had to deal with inliner-specific behavior.
1 parent b3baab2 commit ebf32a2

File tree

2 files changed

+47
-19
lines changed

2 files changed

+47
-19
lines changed

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

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ import core.tasty.TreePickler.Hole
2222
* @param newOwners New owners, replacing previous owners.
2323
* @param substFrom The symbols that need to be substituted.
2424
* @param substTo The substitution targets.
25-
* @param stopAtInlinedArgument Whether one should stop at an inlined argument,
26-
* i.e. a node of form Inlined(EmptyTree, _, _).
2725
*
2826
* The reason the substitution is broken out from the rest of the type map is
2927
* that all symbols have to be substituted at the same time. If we do not do this,
@@ -38,16 +36,24 @@ import core.tasty.TreePickler.Hole
3836
* nested scopes. Any subclass of TreeTypeMap would revert to the standard
3937
* TreeTypeMap in these recursive invocations.
4038
*/
41-
final class TreeTypeMap(
39+
class TreeTypeMap(
4240
val typeMap: Type => Type = IdentityTypeMap,
4341
val treeMap: tpd.Tree => tpd.Tree = identity _,
4442
val oldOwners: List[Symbol] = Nil,
4543
val newOwners: List[Symbol] = Nil,
4644
val substFrom: List[Symbol] = Nil,
47-
val substTo: List[Symbol] = Nil,
48-
stopAtInlinedArgument: Boolean = false)(using Context) extends tpd.TreeMap {
45+
val substTo: List[Symbol] = Nil)(using Context) extends tpd.TreeMap {
4946
import tpd._
5047

48+
def copy(
49+
typeMap: Type => Type,
50+
treeMap: tpd.Tree => tpd.Tree,
51+
oldOwners: List[Symbol],
52+
newOwners: List[Symbol],
53+
substFrom: List[Symbol],
54+
substTo: List[Symbol])(using Context): TreeTypeMap =
55+
new TreeTypeMap(typeMap, treeMap, oldOwners, newOwners, substFrom, substTo)
56+
5157
/** If `sym` is one of `oldOwners`, replace by corresponding symbol in `newOwners` */
5258
def mapOwner(sym: Symbol): Symbol = sym.subst(oldOwners, newOwners)
5359

@@ -119,15 +125,8 @@ final class TreeTypeMap(
119125
val (tmap1, stats1) = transformDefs(stats)
120126
val expr1 = tmap1.transform(expr)
121127
cpy.Block(blk)(stats1, expr1)
122-
case inlined @ Inlined(call, bindings, expanded) =>
123-
if stopAtInlinedArgument && call.isEmpty then
124-
expanded match
125-
case expanded: TypeTree => assert(bindings.isEmpty); expanded
126-
case _ => inlined
127-
else
128-
val (tmap1, bindings1) = transformDefs(bindings)
129-
val expanded1 = tmap1.transform(expanded)
130-
cpy.Inlined(inlined)(call, bindings1, expanded1)
128+
case inlined: Inlined =>
129+
transformInlined(inlined)
131130
case cdef @ CaseDef(pat, guard, rhs) =>
132131
val tmap = withMappedSyms(patVars(pat))
133132
val pat1 = tmap.transform(pat)
@@ -183,14 +182,13 @@ final class TreeTypeMap(
183182
assert(!to.exists(substFrom contains _))
184183
assert(!from.exists(newOwners contains _))
185184
assert(!to.exists(oldOwners contains _))
186-
new TreeTypeMap(
185+
copy(
187186
typeMap,
188187
treeMap,
189188
from ++ oldOwners,
190189
to ++ newOwners,
191190
from ++ substFrom,
192-
to ++ substTo,
193-
stopAtInlinedArgument)
191+
to ++ substTo)
194192
}
195193

196194
/** Apply `typeMap` and `ownerMap` to given symbols `syms`

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

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -706,11 +706,40 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
706706
def inlinedFromOutside(tree: Tree)(span: Span): Tree =
707707
Inlined(EmptyTree, Nil, tree)(using ctx.withSource(inlinedMethod.topLevelClass.source)).withSpan(span)
708708

709+
// InlinerMap is a TreeTypeMap with special treatment for inlined arguments:
710+
// They are generally left alone (not mapped further, and if they wrap a type
711+
// the type Inlined wrapper gets dropped
712+
class InlinerMap(
713+
typeMap: Type => Type,
714+
treeMap: Tree => Tree,
715+
oldOwners: List[Symbol],
716+
newOwners: List[Symbol],
717+
substFrom: List[Symbol],
718+
substTo: List[Symbol])(using Context)
719+
extends TreeTypeMap(typeMap, treeMap, oldOwners, newOwners, substFrom, substTo):
720+
721+
override def copy(
722+
typeMap: Type => Type,
723+
treeMap: Tree => Tree,
724+
oldOwners: List[Symbol],
725+
newOwners: List[Symbol],
726+
substFrom: List[Symbol],
727+
substTo: List[Symbol])(using Context) =
728+
new InlinerMap(typeMap, treeMap, oldOwners, newOwners, substFrom, substTo)
729+
730+
override def transformInlined(tree: Inlined)(using Context) =
731+
if tree.call.isEmpty then
732+
tree.expansion match
733+
case expansion: TypeTree => expansion
734+
case _ => tree
735+
else super.transformInlined(tree)
736+
end InlinerMap
737+
709738
// A tree type map to prepare the inlined body for typechecked.
710739
// The translation maps references to `this` and parameters to
711740
// corresponding arguments or proxies on the type and term level. It also changes
712741
// the owner from the inlined method to the current owner.
713-
val inliner = new TreeTypeMap(
742+
val inliner = new InlinerMap(
714743
typeMap =
715744
new DeepTypeMap {
716745
def apply(t: Type) = t match {
@@ -753,7 +782,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
753782
},
754783
oldOwners = inlinedMethod :: Nil,
755784
newOwners = ctx.owner :: Nil,
756-
stopAtInlinedArgument = true
785+
substFrom = Nil,
786+
substTo = Nil
757787
)(using inlineCtx)
758788

759789
// Apply inliner to `rhsToInline`, split off any implicit bindings from result, and

0 commit comments

Comments
 (0)