Skip to content

Commit 3e6d2dc

Browse files
Fix type params not being replaced in RHS
Move inline trait related code back from Inliner to InlineParentTrait Use overridden version of DeepTypeMap to replace types in RHS of definitions Add test with trait-related type param in RHS
1 parent 664b8b6 commit 3e6d2dc

File tree

3 files changed

+44
-39
lines changed

3 files changed

+44
-39
lines changed

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

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ class Inliner(val call: tpd.Tree)(using Context):
158158
for arg <- callTypeArgs do
159159
isFullyDefined(arg.tpe, ForceDegree.flipBottom)
160160

161-
/** A map from parameter names of the inlineable method or trait to references of the actual arguments.
161+
/** A map from parameter names of the inlineable method to references of the actual arguments.
162162
* For a type argument this is the full argument type.
163163
* For a value argument, it is a reference to either the argument value
164164
* (if the argument is a pure expression of singleton type), or to `val` or `def` acting
@@ -169,7 +169,7 @@ class Inliner(val call: tpd.Tree)(using Context):
169169
/** A map from parameter names of the inlineable method to spans of the actual arguments */
170170
private val paramSpan = new mutable.HashMap[Name, Span]
171171

172-
/** A map from references to (type and value) parameters of the inlineable method or trait
172+
/** A map from references to (type and value) parameters of the inlineable method
173173
* to their corresponding argument or proxy references, as given by `paramBinding`.
174174
*/
175175
private[inlines] val paramProxy = new mutable.HashMap[Type, Type]
@@ -187,8 +187,7 @@ class Inliner(val call: tpd.Tree)(using Context):
187187
*
188188
* These are different (wrt ==) types but represent logically the same key
189189
*/
190-
protected val thisProxy = new mutable.HashMap[ClassSymbol, TermRef]
191-
protected val thisInlineTraitProxy = new mutable.HashMap[ClassSymbol, ThisType]
190+
private val thisProxy = new mutable.HashMap[ClassSymbol, TermRef]
192191

193192
/** A buffer for bindings that define proxies for actual arguments */
194193
private val bindingsBuf = new mutable.ListBuffer[ValOrDefDef]
@@ -439,11 +438,10 @@ class Inliner(val call: tpd.Tree)(using Context):
439438

440439
private def adaptToPrefix(tp: Type) = tp.asSeenFrom(inlineCallPrefix.tpe, inlinedMethod.owner)
441440

442-
/** Populate `thisProxy`, `thisInlineTraitProxy` and `paramProxy` as follows:
441+
/** Populate `thisProxy` and `paramProxy` as follows:
443442
*
444443
* 1a. If given type refers to a static this, thisProxy binds it to corresponding global reference,
445-
* 1b. If given type refers to an inline trait, thisInlineTraitProxy binds it to the corresponding thistype,
446-
* 1c. If given type refers to an instance this to a class that is not contained in the
444+
* 1b. If given type refers to an instance this to a class that is not contained in the
447445
* inline method, create a proxy symbol and bind the thistype to refer to the proxy.
448446
* The proxy is not yet entered in `bindingsBuf`; that will come later.
449447
* 2. If given type refers to a parameter, make `paramProxy` refer to the entry stored
@@ -453,7 +451,7 @@ class Inliner(val call: tpd.Tree)(using Context):
453451
* and MethodParams, not TypeRefs or TermRefs.
454452
*/
455453
private def registerType(tpe: Type): Unit = tpe match {
456-
case tpe: ThisType if !canElideThis(tpe) && !thisProxy.contains(tpe.cls) =>
454+
case tpe: ThisType if !canElideThis(tpe) && !thisProxy.contains(tpe.cls) && !tpe.cls.isInlineTrait =>
457455
val proxyName = s"${tpe.cls.name}_this".toTermName
458456
val proxyType = inlineCallPrefix.tpe.dealias.tryNormalize match {
459457
case typeMatchResult if typeMatchResult.exists => typeMatchResult
@@ -462,10 +460,6 @@ class Inliner(val call: tpd.Tree)(using Context):
462460
thisProxy(tpe.cls) = newSym(proxyName, InlineProxy, proxyType).termRef
463461
for (param <- tpe.cls.typeParams)
464462
paramProxy(param.typeRef) = adaptToPrefix(param.typeRef)
465-
case tpe: ThisType if tpe.cls.isInlineTrait =>
466-
thisInlineTraitProxy(tpe.cls) = ThisType.raw(TypeRef(ctx.owner.prefix, ctx.owner))
467-
for (param <- tpe.cls.typeParams)
468-
paramProxy(param.typeRef) = adaptToPrefix(param.typeRef)
469463
case tpe: NamedType
470464
if tpe.symbol.is(Param)
471465
&& tpe.symbol.owner == inlinedMethod
@@ -510,9 +504,23 @@ class Inliner(val call: tpd.Tree)(using Context):
510504

511505
val reducer = new InlineReducer(this)
512506

507+
protected class InlinerTypeMap extends DeepTypeMap {
508+
override def stopAt =
509+
if opaqueProxies.isEmpty then StopAt.Static else StopAt.Package
510+
def apply(t: Type) = t match {
511+
case t: ThisType => thisProxy.get(t.cls).getOrElse(t)
512+
case t: TypeRef => paramProxy.getOrElse(t, mapOver(t))
513+
case t: SingletonType =>
514+
if t.termSymbol.isAllOf(InlineParam) then apply(t.widenTermRefExpr)
515+
else paramProxy.getOrElse(t, mapOver(t))
516+
case t => mapOver(t)
517+
}
518+
}
519+
520+
protected val inlinerTypeMap: InlinerTypeMap = InlinerTypeMap()
521+
513522
/** The Inlined node representing the inlined call */
514523
def inlined(rhsToInline: tpd.Tree): (List[MemberDef], Tree) =
515-
516524
inlining.println(i"-----------------------\nInlining $call\nWith RHS $rhsToInline")
517525

518526
def paramTypess(call: Tree, acc: List[List[Type]]): List[List[Type]] = call match
@@ -564,19 +572,7 @@ class Inliner(val call: tpd.Tree)(using Context):
564572
// corresponding arguments or proxies on the type and term level. It also changes
565573
// the owner from the inlined method to the current owner.
566574
val inliner = new InlinerMap(
567-
typeMap =
568-
new DeepTypeMap {
569-
override def stopAt =
570-
if opaqueProxies.isEmpty then StopAt.Static else StopAt.Package
571-
def apply(t: Type) = t match {
572-
case t: ThisType => thisProxy.get(t.cls).orElse(thisInlineTraitProxy.get(t.cls)).getOrElse(t)
573-
case t: TypeRef => paramProxy.getOrElse(t, mapOver(t))
574-
case t: SingletonType =>
575-
if t.termSymbol.isAllOf(InlineParam) then apply(t.widenTermRefExpr)
576-
else paramProxy.getOrElse(t, mapOver(t))
577-
case t => mapOver(t)
578-
}
579-
},
575+
typeMap = inlinerTypeMap,
580576
treeMap = {
581577
case tree: This =>
582578
tree.tpe match {
@@ -625,7 +621,6 @@ class Inliner(val call: tpd.Tree)(using Context):
625621
inlining.println(
626622
i"""inliner transform with
627623
|thisProxy = ${thisProxy.toList.map(_._1)}%, % --> ${thisProxy.toList.map(_._2)}%, %
628-
|thisInlineTraitProxy = ${thisInlineTraitProxy.toList.map(_._1)}%, % --> ${thisInlineTraitProxy.toList.map(_._2)}%, %
629624
|paramProxy = ${paramProxy.toList.map(_._1.typeSymbol.showLocated)}%, % --> ${paramProxy.toList.map(_._2)}%, %""")
630625

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

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

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ object Inlines:
172172

173173
def inlineParentTrait(parent: tpd.Tree, childOverrideDecls: Set[Symbol])(using Context): List[Tree] =
174174
val traitSym = if parent.symbol.isConstructor then parent.symbol.owner else parent.symbol
175-
if traitSym.isInlineTrait then InlineParentTrait(parent, traitSym, childOverrideDecls).expandDefs()
175+
if traitSym.isInlineTrait then InlineParentTrait(parent, traitSym.asClass, childOverrideDecls).expandDefs()
176176
else Nil
177177

178178
/** Try to inline a pattern with an inline unapply method. Fail with error if the maximal
@@ -466,17 +466,28 @@ object Inlines:
466466
end expand
467467
end InlineCall
468468

469-
private class InlineParentTrait(parent: tpd.Tree, parentSym: Symbol, overriddenDecls: Set[Symbol])(using Context) extends Inliner(parent):
469+
private class InlineParentTrait(parent: tpd.Tree, parentSym: ClassSymbol, overriddenDecls: Set[Symbol])(using Context) extends Inliner(parent):
470470
import tpd._
471471
import Inlines.*
472472

473+
private val thisInlineTraitProxy = ThisType.raw(TypeRef(ctx.owner.prefix, ctx.owner))
474+
473475
def expandDefs(): List[Tree] =
474476
val tpd.Block(stats, _) = Inlines.bodyToInline(parentSym): @unchecked
475477
val stats1 = stats.filterNot(isMemberOverridden)
476478
val inlinedSymbols = stats1.map(stat => inlinedMember(stat.symbol))
477479
stats1.zip(inlinedSymbols).map(expandStat)//.map(inlined(_)._2)
478480
end expandDefs
479481

482+
protected class InlineTraitTypeMap extends InlinerTypeMap {
483+
override def apply(t: Type) = t match {
484+
case t: ThisType if t.cls == parentSym => thisInlineTraitProxy
485+
case t => super.apply(t)
486+
}
487+
}
488+
489+
override protected val inlinerTypeMap: InlinerTypeMap = InlineTraitTypeMap()
490+
480491
private val argsMap: Map[Name, Tree] =
481492
def allArgs(tree: Tree): List[List[Tree]] = tree match
482493
case Apply(fun, args) => args :: allArgs(fun)
@@ -492,13 +503,6 @@ object Inlines:
492503
else parent.symbol.info
493504
allParams(info).flatten.zip(allArgs(parent).reverse.flatten).toMap
494505

495-
private val substituteTypeParams = new TypeMap {
496-
override def apply(t: Type): Type = t match
497-
case TypeRef(ths: ThisType, sym: Symbol) if ths.cls == parentSym =>
498-
argsMap.get(sym.name).map(_.tpe).getOrElse(t)
499-
case t => mapOver(t)
500-
}
501-
502506
private def isMemberOverridden(stat: Tree): Boolean =
503507
overriddenDecls.flatMap(_.allOverriddenSymbols).toSet.contains(stat.symbol)
504508

@@ -528,7 +532,7 @@ object Inlines:
528532
sym.copy(
529533
owner = ctx.owner,
530534
flags = flags,
531-
info = substituteTypeParams(sym.info),
535+
info = inlinerTypeMap(sym.info),
532536
coord = spanCoord(parent.span)).entered
533537

534538
private def inlinedValDef(vdef: ValDef, inlinedSym: Symbol)(using Context): ValDef =
@@ -572,7 +576,7 @@ object Inlines:
572576
// TODO case tree: TypeDef => cloneTypeDef(tree)
573577

574578
private def cloneDefDef(ddef: DefDef)(using Context): DefDef =
575-
val inlinedSym = ddef.symbol.copy(owner = ctx.owner, info = substituteTypeParams(ddef.symbol.info), coord = spanCoord(parent.span)).entered
579+
val inlinedSym = ddef.symbol.copy(owner = ctx.owner, info = inlinerTypeMap(ddef.symbol.info), coord = spanCoord(parent.span)).entered
576580
def rhsFun(paramss: List[List[Tree]]): Tree =
577581
val oldParamSyms = ddef.paramss.flatten.map(_.symbol)
578582
val newParamSyms = paramss.flatten.map(_.symbol)
@@ -584,7 +588,7 @@ object Inlines:
584588
cpy.DefDef(constr)(tpt = TypeTree(defn.UnitType), rhs = EmptyTree)
585589

586590
private def cloneValDef(vdef: ValDef)(using Context): ValDef =
587-
val inlinedSym = vdef.symbol.copy(owner = ctx.owner, info = substituteTypeParams(vdef.symbol.info), coord = spanCoord(parent.span)).entered
591+
val inlinedSym = vdef.symbol.copy(owner = ctx.owner, info = inlinerTypeMap(vdef.symbol.info), coord = spanCoord(parent.span)).entered
588592
tpd.ValDef(inlinedSym.asTerm, inlinedRhs(vdef.rhs.changeOwner(vdef.symbol, inlinedSym))).withSpan(parent.span) // TODO clone local classes?
589593

590594
private def cloneTypeDef(tdef: TypeDef)(using Context): TypeDef =
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
inline trait A[T](x: T):
2+
def f: T = x: T
3+
def g: T = identity[T](x)
4+
def h: this.type = this: this.type
5+
6+
class B extends A("Hello")

0 commit comments

Comments
 (0)