Skip to content

Commit c48fb9b

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 c48fb9b

File tree

2 files changed

+47
-23
lines changed

2 files changed

+47
-23
lines changed

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

Lines changed: 15 additions & 21 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,
@@ -33,21 +31,25 @@ import core.tasty.TreePickler.Hole
3331
* do S2 we get outer#2.inner#4. But that means that the named type outer#2.inner
3432
* gets two different denotations in the same period. Hence, if -Yno-double-bindings is
3533
* set, we would get a data race assertion error.
36-
*
37-
* Note: TreeTypeMap is final, since derived maps are created dynamically for
38-
* nested scopes. Any subclass of TreeTypeMap would revert to the standard
39-
* TreeTypeMap in these recursive invocations.
4034
*/
41-
final class TreeTypeMap(
35+
class TreeTypeMap(
4236
val typeMap: Type => Type = IdentityTypeMap,
4337
val treeMap: tpd.Tree => tpd.Tree = identity _,
4438
val oldOwners: List[Symbol] = Nil,
4539
val newOwners: List[Symbol] = Nil,
4640
val substFrom: List[Symbol] = Nil,
47-
val substTo: List[Symbol] = Nil,
48-
stopAtInlinedArgument: Boolean = false)(using Context) extends tpd.TreeMap {
41+
val substTo: List[Symbol] = Nil)(using Context) extends tpd.TreeMap {
4942
import tpd._
5043

44+
def copy(
45+
typeMap: Type => Type,
46+
treeMap: tpd.Tree => tpd.Tree,
47+
oldOwners: List[Symbol],
48+
newOwners: List[Symbol],
49+
substFrom: List[Symbol],
50+
substTo: List[Symbol])(using Context): TreeTypeMap =
51+
new TreeTypeMap(typeMap, treeMap, oldOwners, newOwners, substFrom, substTo)
52+
5153
/** If `sym` is one of `oldOwners`, replace by corresponding symbol in `newOwners` */
5254
def mapOwner(sym: Symbol): Symbol = sym.subst(oldOwners, newOwners)
5355

@@ -119,15 +121,8 @@ final class TreeTypeMap(
119121
val (tmap1, stats1) = transformDefs(stats)
120122
val expr1 = tmap1.transform(expr)
121123
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)
124+
case inlined: Inlined =>
125+
transformInlined(inlined)
131126
case cdef @ CaseDef(pat, guard, rhs) =>
132127
val tmap = withMappedSyms(patVars(pat))
133128
val pat1 = tmap.transform(pat)
@@ -183,14 +178,13 @@ final class TreeTypeMap(
183178
assert(!to.exists(substFrom contains _))
184179
assert(!from.exists(newOwners contains _))
185180
assert(!to.exists(oldOwners contains _))
186-
new TreeTypeMap(
181+
copy(
187182
typeMap,
188183
treeMap,
189184
from ++ oldOwners,
190185
to ++ newOwners,
191186
from ++ substFrom,
192-
to ++ substTo,
193-
stopAtInlinedArgument)
187+
to ++ substTo)
194188
}
195189

196190
/** 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)