@@ -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.isRetainedInlineMethod 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,50 @@ object Erasure {
874892            outerParamDefs(constr)
875893      else  Nil 
876894
895+     /**  For all statements in stats: given a retained inline method and 
896+      *  its retainedBody method such as 
897+      * 
898+      *     inline override def f(x: T) = body1 
899+      *     private def f$retainedBody(x: T) = body2 
900+      * 
901+      *  return the runtime version of `f` as 
902+      * 
903+      *     override def f(x: T) = body2 
904+      * 
905+      *  Here, the owner of body2 is changed to f and all references 
906+      *  to parameters of f$retainedBody are changed to references of 
907+      *  corresponding parameters in f. 
908+      * 
909+      *  `f$retainedBody` is subseqently mapped to the empty tree in `typedDefDef` 
910+      *  which is then dropped in `typedStats`. 
911+      */  
912+     private  def  addRetainedInlineBodies (stats : List [untpd.Tree ])(using  ctx : Context ):  List [untpd.Tree ] = 
913+       lazy  val  retainerDef :  Map [Symbol , DefDef ] =  stats.collect {
914+         case  stat : DefDef  if  stat.symbol.name.is(BodyRetainerName ) => 
915+           val  retainer  =  stat.symbol
916+           val  origName  =  retainer.name.asTermName.exclude(BodyRetainerName )
917+           val  inlineMeth  =  ctx.atPhase(ctx.typerPhase) {
918+             retainer.owner.info.decl(origName)
919+               .matchingDenotation(retainer.owner.thisType, stat.symbol.info)
920+               .symbol
921+           }
922+           (inlineMeth, stat)
923+       }.toMap
924+       stats.mapConserve {
925+         case  stat : DefDef  if  stat.symbol.isRetainedInlineMethod => 
926+           val  rdef  =  retainerDef(stat.symbol)
927+           val  fromParams  =  untpd.allParamSyms(rdef)
928+           val  toParams  =  untpd.allParamSyms(stat)
929+           assert(fromParams.hasSameLengthAs(toParams))
930+           val  mapBody  =  TreeTypeMap (
931+             oldOwners =  rdef.symbol ::  Nil ,
932+             newOwners =  stat.symbol ::  Nil ,
933+             substFrom =  fromParams,
934+             substTo   =  toParams)
935+           cpy.DefDef (stat)(rhs =  mapBody.transform(rdef.rhs))
936+         case  stat =>  stat
937+       }
938+ 
877939    override  def  typedClosure (tree : untpd.Closure , pt : Type )(implicit  ctx : Context ):  Tree  =  {
878940      val  xxl  =  defn.isXXLFunctionClass(tree.typeOpt.typeSymbol)
879941      var  implClosure  =  super .typedClosure(tree, pt).asInstanceOf [Closure ]
@@ -888,9 +950,10 @@ object Erasure {
888950      typed(tree.arg, pt)
889951
890952    override  def  typedStats (stats : List [untpd.Tree ], exprOwner : Symbol )(implicit  ctx : Context ):  (List [Tree ], Context ) =  {
953+       val  stats0  =  addRetainedInlineBodies(stats)(using  preErasureCtx)
891954      val  stats1  = 
892-         if  (takesBridges(ctx.owner)) new  Bridges (ctx.owner.asClass, erasurePhase).add(stats )
893-         else  stats 
955+         if  (takesBridges(ctx.owner)) new  Bridges (ctx.owner.asClass, erasurePhase).add(stats0 )
956+         else  stats0 
894957      val  (stats2, finalCtx) =  super .typedStats(stats1, exprOwner)
895958      (stats2.filter(! _.isEmpty), finalCtx)
896959    }
0 commit comments