@@ -12,17 +12,19 @@ import core.Types._
12
12
import core .Names ._
13
13
import core .StdNames ._
14
14
import core .NameOps ._
15
- import core .NameKinds .AdaptedClosureName
15
+ import core .NameKinds .{ AdaptedClosureName , BodyRetainerName }
16
16
import core .Decorators ._
17
17
import core .Constants ._
18
18
import core .Definitions ._
19
+ import core .Annotations .BodyAnnotation
19
20
import typer .{NoChecking , LiftErased }
20
21
import typer .Inliner
21
22
import typer .ProtoTypes ._
22
23
import core .TypeErasure ._
23
24
import core .Decorators ._
24
25
import dotty .tools .dotc .ast .{tpd , untpd }
25
26
import ast .Trees ._
27
+ import ast .TreeTypeMap
26
28
import dotty .tools .dotc .core .{Constants , Flags }
27
29
import ValueClasses ._
28
30
import TypeUtils ._
@@ -78,17 +80,32 @@ class Erasure extends Phase with DenotTransformer {
78
80
val oldInfo = ref.info
79
81
val newInfo = transformInfo(oldSymbol, oldInfo)
80
82
val oldFlags = ref.flags
81
- val newFlags =
83
+ var newFlags =
82
84
if (oldSymbol.is(Flags .TermParam ) && isCompacted(oldSymbol.owner)) oldFlags &~ Flags .Param
83
85
else oldFlags &~ Flags .HasDefaultParamsFlags // HasDefaultParamsFlags needs to be dropped because overriding might become overloading
84
-
86
+ val oldAnnotations = ref.annotations
87
+ var newAnnotations = oldAnnotations
88
+ if oldSymbol.isInlineMethod && oldSymbol.isInlineRetained then
89
+ newFlags = newFlags &~ Flags .Inline
90
+ newAnnotations = newAnnotations.filterConserve(! _.isInstanceOf [BodyAnnotation ])
85
91
// TODO: define derivedSymDenotation?
86
- if ((oldSymbol eq newSymbol) && (oldOwner eq newOwner) && (oldName eq newName) && (oldInfo eq newInfo) && (oldFlags == newFlags))
92
+ if (oldSymbol eq newSymbol)
93
+ && (oldOwner eq newOwner)
94
+ && (oldName eq newName)
95
+ && (oldInfo eq newInfo)
96
+ && (oldFlags == newFlags)
97
+ && (oldAnnotations eq newAnnotations)
98
+ then
87
99
ref
88
- else {
100
+ else
89
101
assert(! ref.is(Flags .PackageClass ), s " trans $ref @ ${ctx.phase} oldOwner = $oldOwner, newOwner = $newOwner, oldInfo = $oldInfo, newInfo = $newInfo ${oldOwner eq newOwner} ${oldInfo eq newInfo}" )
90
- ref.copySymDenotation(symbol = newSymbol, owner = newOwner, name = newName, initFlags = newFlags, info = newInfo)
91
- }
102
+ ref.copySymDenotation(
103
+ symbol = newSymbol,
104
+ owner = newOwner,
105
+ name = newName,
106
+ initFlags = newFlags,
107
+ info = newInfo,
108
+ annotations = newAnnotations)
92
109
}
93
110
case ref : JointRefDenotation =>
94
111
new UniqueRefDenotation (
@@ -813,7 +830,8 @@ object Erasure {
813
830
* parameter of type `[]Object`.
814
831
*/
815
832
override def typedDefDef (ddef : untpd.DefDef , sym : Symbol )(implicit ctx : Context ): Tree =
816
- if (sym.isEffectivelyErased) erasedDef(sym)
833
+ if sym.isEffectivelyErased || sym.name.is(BodyRetainerName ) then
834
+ erasedDef(sym)
817
835
else
818
836
val restpe = if sym.isConstructor then defn.UnitType else sym.info.resultType
819
837
var vparams = outerParamDefs(sym)
@@ -874,6 +892,35 @@ object Erasure {
874
892
outerParamDefs(constr)
875
893
else Nil
876
894
895
+ private def addRetainedInlineBodies (stats : List [untpd.Tree ])(using ctx : Context ): List [untpd.Tree ] =
896
+ lazy val retainerDef : Map [Symbol , DefDef ] = stats.collect {
897
+ case stat : DefDef if stat.symbol.name.is(BodyRetainerName ) =>
898
+ val retainer = stat.symbol
899
+ val origName = retainer.name.asTermName.exclude(BodyRetainerName )
900
+ val inlineMeth = ctx.atPhase(ctx.typerPhase) {
901
+ retainer.owner.info.decl(origName)
902
+ .matchingDenotation(retainer.owner.thisType, stat.symbol.info)
903
+ .symbol
904
+ }
905
+ (inlineMeth, stat)
906
+ }.toMap
907
+ stats.mapConserve {
908
+ case stat : DefDef if stat.symbol.isInlineMethod && stat.symbol.isInlineRetained =>
909
+ val rdef = retainerDef(stat.symbol)
910
+ def allParams (ddef : DefDef ) =
911
+ (ddef.tparams ::: ddef.vparamss.flatten).map(_.symbol)
912
+ val fromParams = allParams(rdef)
913
+ val toParams = allParams(stat)
914
+ assert(fromParams.hasSameLengthAs(toParams))
915
+ val mapBody = TreeTypeMap (
916
+ oldOwners = rdef.symbol :: Nil ,
917
+ newOwners = stat.symbol :: Nil ,
918
+ substFrom = fromParams,
919
+ substTo = toParams)
920
+ cpy.DefDef (stat)(rhs = mapBody.transform(rdef.rhs))
921
+ case stat => stat
922
+ }
923
+
877
924
override def typedClosure (tree : untpd.Closure , pt : Type )(implicit ctx : Context ): Tree = {
878
925
val xxl = defn.isXXLFunctionClass(tree.typeOpt.typeSymbol)
879
926
var implClosure = super .typedClosure(tree, pt).asInstanceOf [Closure ]
@@ -888,9 +935,10 @@ object Erasure {
888
935
typed(tree.arg, pt)
889
936
890
937
override def typedStats (stats : List [untpd.Tree ], exprOwner : Symbol )(implicit ctx : Context ): (List [Tree ], Context ) = {
938
+ val stats0 = addRetainedInlineBodies(stats)(using preErasureCtx)
891
939
val stats1 =
892
- if (takesBridges(ctx.owner)) new Bridges (ctx.owner.asClass, erasurePhase).add(stats )
893
- else stats
940
+ if (takesBridges(ctx.owner)) new Bridges (ctx.owner.asClass, erasurePhase).add(stats0 )
941
+ else stats0
894
942
val (stats2, finalCtx) = super .typedStats(stats1, exprOwner)
895
943
(stats2.filter(! _.isEmpty), finalCtx)
896
944
}
0 commit comments