@@ -12,17 +12,19 @@ import core.Types._
1212import core .Names ._
1313import core .StdNames ._
1414import core .NameOps ._
15- import core .NameKinds .AdaptedClosureName
15+ import core .NameKinds .{ AdaptedClosureName , BodyRetainerName }
1616import core .Decorators ._
1717import core .Constants ._
1818import core .Definitions ._
19+ import core .Annotations .BodyAnnotation
1920import typer .{NoChecking , LiftErased }
2021import typer .Inliner
2122import typer .ProtoTypes ._
2223import core .TypeErasure ._
2324import core .Decorators ._
2425import dotty .tools .dotc .ast .{tpd , untpd }
2526import ast .Trees ._
27+ import ast .TreeTypeMap
2628import dotty .tools .dotc .core .{Constants , Flags }
2729import ValueClasses ._
2830import TypeUtils ._
@@ -78,17 +80,32 @@ class Erasure extends Phase with DenotTransformer {
7880 val oldInfo = ref.info
7981 val newInfo = transformInfo(oldSymbol, oldInfo)
8082 val oldFlags = ref.flags
81- val newFlags =
83+ var newFlags =
8284 if (oldSymbol.is(Flags .TermParam ) && isCompacted(oldSymbol.owner)) oldFlags &~ Flags .Param
8385 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 ])
8591 // 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
8799 ref
88- else {
100+ else
89101 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)
92109 }
93110 case ref : JointRefDenotation =>
94111 new UniqueRefDenotation (
@@ -813,7 +830,8 @@ object Erasure {
813830 * parameter of type `[]Object`.
814831 */
815832 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)
817835 else
818836 val restpe = if sym.isConstructor then defn.UnitType else sym.info.resultType
819837 var vparams = outerParamDefs(sym)
@@ -874,6 +892,35 @@ object Erasure {
874892 outerParamDefs(constr)
875893 else Nil
876894
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+
877924 override def typedClosure (tree : untpd.Closure , pt : Type )(implicit ctx : Context ): Tree = {
878925 val xxl = defn.isXXLFunctionClass(tree.typeOpt.typeSymbol)
879926 var implClosure = super .typedClosure(tree, pt).asInstanceOf [Closure ]
@@ -888,9 +935,10 @@ object Erasure {
888935 typed(tree.arg, pt)
889936
890937 override def typedStats (stats : List [untpd.Tree ], exprOwner : Symbol )(implicit ctx : Context ): (List [Tree ], Context ) = {
938+ val stats0 = addRetainedInlineBodies(stats)(using preErasureCtx)
891939 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
894942 val (stats2, finalCtx) = super .typedStats(stats1, exprOwner)
895943 (stats2.filter(! _.isEmpty), finalCtx)
896944 }
0 commit comments