@@ -22,13 +22,13 @@ import dotty.tools.dotc.util.Property
2222import dotty .tools .dotc .cc .pathOwner
2323import scala .annotation .tailrec
2424
25- class ErasurePreservation extends MiniPhase with InfoTransformer {
25+ class ErasurePreservation extends MiniPhase {
2626
2727 override def phaseName : String = ErasurePreservation .name
2828
2929 override def description : String = ErasurePreservation .description
3030
31- def toTypeA (tp : Type , sourceSym : Symbol )(using Context ): TypeA = trace(s " toTypeA ${tp}" ) {tp match
31+ def toTypeA (tp : Type , outers : List [ List [ Symbol ]] )(using Context ): TypeA = trace(i " toTypeA ${tp}" ){ tp.widen match
3232 case tpr : TypeParamRef => TypeA .M (tpr.paramNum)
3333 case tr : TypeRef =>
3434 // println(tr.symbol.owner.paramSymss)
@@ -41,90 +41,139 @@ class ErasurePreservation extends MiniPhase with InfoTransformer {
4141 if tr.isRef(defn.ShortClass ) then TypeA .Short else
4242 if tr.isRef(defn.BooleanClass ) then TypeA .Boolean else
4343 if tr.symbol.isTypeParam then
44- val owner = tr.symbol.owner
45- if owner.isClass then
46- val ind = owner.typeParams.indexOf(tr.symbol)
47- val n = debrujin(sourceSym.enclosingClass, owner )
48- if ind != - 1 then TypeA . K (n, ind) else ???
49- else
50- val ind = owner.paramSymss.headOption match
51- case None => assert( false , i " Got unexpected type ${tp} " )
52- case Some (value) => value.indexWhere(tr.isRef(_) )
53- if ind != - 1 then TypeA . M (ind) else ???
44+ def search ( tr : TypeRef , depth : Int , outers : List [ List [ Symbol ]]) : TypeA =
45+ outers.head.indexOf(tr.symbol) match
46+ case - 1 =>
47+ search(tr, depth + 1 , outers.tail )
48+ case ind =>
49+ if depth != 0 then
50+ TypeA . K (depth - 1 , ind)
51+ else
52+ TypeA . M (ind )
53+ search(tr, 0 , outers)
5454 else TypeA .Ref
55- case _ => assert(false )
55+ case _ =>
56+ TypeA .Ref
5657 }
5758
58- def debrujin (source : Symbol , outer : Symbol )(using Context ): Int = trace(i " debrujin: $source, $outer" ) {
59- if (source.enclosingClass == outer) then 0
60- else debrujin(source.owner, outer)+ 1
61- }
59+ def indexTypeParam (method : Type , tpr : TypeParamRef ): Int = method match
60+ case pt : PolyType =>
61+ if tpr.binder == pt then
62+ tpr.paramNum
63+ else indexTypeParam(pt.resType, tpr) + pt.paramNames.size
64+ case mt : MethodType => indexTypeParam(mt.resType, tpr)
65+ case _ => ???
66+
6267
63- def toTypeB (tp : Type , sourceSym : Symbol )(using Context ): TypeB = trace(i " toTypeB ${tp}" ){ tp match
64- case tpr : TypeParamRef => TypeB .M (tpr.paramNum)
68+ def toTypeB (tp : Type , outers : List [List [Symbol ]], isConstructor : Boolean = false )(using Context ): TypeB = trace(i " toTypeB ${tp}, ${outers}" ){ tp match
69+ case tpr : TypeParamRef =>
70+ TypeB .M (outers.head.indexWhere(sym => sym.name == tpr.paramName))
6571 case tr : TypeRef if tr.symbol.isTypeParam =>
66- val owner = tr.symbol.owner
67- if owner.isClass then
68- val ind = owner.typeParams.indexOf(tr.symbol)
69- val n = debrujin(sourceSym.enclosingClass, owner)
70- if ind != - 1 then TypeB .K (n, ind) else TypeB .None
71- else
72- val ind = owner.paramSymss.headOption match
73- case None => assert(false , i " Got unexpected type ${tp}" )
74- case Some (value) => value.indexWhere(tr.isRef(_))
75- if ind != - 1 then TypeB .M (ind) else TypeB .None
72+ def search (tr : TypeRef , depth : Int , outers : List [List [Symbol ]]): TypeB =
73+ outers.head.indexOf(tr.symbol) match
74+ case - 1 =>
75+ search(tr, depth+ 1 , outers.tail)
76+ case ind =>
77+ if depth != 0 then
78+ if isConstructor then
79+ TypeB .K (depth, ind)
80+ else
81+ TypeB .K (depth- 1 , ind)
82+ else
83+ TypeB .M (ind)
84+ search(tr, 0 , outers)
85+ case at : AppliedType if at.tycon.isRef(defn.ArrayClass ) =>
86+ TypeB .Array (toTypeB(at.args.head, outers))
7687 case _ => TypeB .None
7788 }
7889
79- def toReturnTypeB (tp : Type , sourceSym : Symbol )(using Context ): TypeB = tp match
90+ def toReturnTypeB (tp : Type , outers : List [ List [ Symbol ]] )(using Context ): TypeB = tp match
8091 case tr : TypeRef if tr.symbol.isTypeParam =>
81- val owner = tr.symbol.owner
82- if owner.isClass then
83- val ind = owner.typeParams.indexOf(tr.symbol)
84- val n = debrujin(sourceSym.enclosingClass, owner)
85- if ind != - 1 then TypeB .K (n, ind) else TypeB .None
86- else
87- val ind = owner.paramSymss.headOption match
88- case None => assert(false , i " Got unexpected type ${tp}" )
89- case Some (value) => value.indexWhere(tr.isRef(_))
90- if ind != - 1 then TypeB .M (ind) else TypeB .None
92+ def search (tr : TypeRef , depth : Int , outers : List [List [Symbol ]]): TypeB =
93+ outers.head.indexOf(tr.symbol) match
94+ case - 1 =>
95+ search(tr, depth+ 1 , outers.tail)
96+ case ind =>
97+ if depth != 0 then
98+ TypeB .K (depth- 1 , ind)
99+ else
100+ TypeB .M (ind)
101+ search(tr, 0 , outers)
102+ case at : AppliedType if at.tycon.isRef(defn.ArrayClass ) =>
103+ TypeB .Array (toTypeB(at.args.head, outers))
91104 case _ => TypeB .None
92105
93- override def transformInfo (tp : Type , sym : Symbol )(using Context ): Type = trace(i " transformInfo ${tp}, ${sym}" ) {
94- tp match
95- case pt : PolyType =>
96- pt.resType match
97- case mt : MethodType =>
98- // println(i"sym context: $sym, ${sym.enclosingClass}, ${sym.enclosingClass.owner}")
99- sym.addAnnotation(ErasedInfo (pt.paramInfos.size, mt.paramInfos.map(p => toTypeB(p, sym)), toTypeB(mt.resType, sym)))
100- case other =>
101- sym.addAnnotation(ErasedInfo (pt.paramInfos.size, Nil , toTypeB(other.widenExpr, sym)))
106+
107+ /**
108+ * Return all outer type parameters that originate from a method
109+ * until we reach a class
110+ */
111+ def getOuterParamss (sym : Symbol , isConstructor : Boolean )(using Context ): List [List [Symbol ]] = trace(i " getOuterParamss ${sym}" ) {
112+ if ! sym.exists then List (List ())
113+ else if sym.isClass && isConstructor then
114+ // println(sym.typeParams)
115+ val outers = getOuterParamss(sym.owner, false )
116+ (outers.head ++ sym.typeParams) :: outers.tail
117+ else if sym.isClass then
118+ val outers = getOuterParamss(sym.owner, false )
119+ List () :: (outers.head ++ sym.typeParams) :: outers.tail
120+ else
121+ val tyParams = sym.paramSymss.headOption
122+ val outers = getOuterParamss(sym.owner, false )
123+ tyParams match
124+ case Some (tps) =>
125+ (outers.head ++ sym.paramSymss.headOption.getOrElse(List ())) :: outers.tail
126+ case None => outers
127+ }
128+
129+ def methodToInfos (
130+ params : List [Type ],
131+ resType : Type ,
132+ tyParams : List [Symbol ],
133+ isConstructor : Boolean )(using Context ): Tuple3 [Int , List [TypeB ], TypeB ] = trace(i " methodToInfos ${params}, ${resType}" )
134+ {
135+ var outers = getOuterParamss(ctx.owner, isConstructor)
136+ if (! isConstructor)
137+ outers = outers.head ++ tyParams :: outers.tail
138+ val paramsTypeB : List [TypeB ] = params.map(tp => toTypeB(tp, outers, isConstructor))
139+ val ret : TypeB = toTypeB(resType, outers, isConstructor)
140+ (outers.head.length, paramsTypeB, ret)
141+ }
142+
143+
144+ override def transformDefDef (tree : tpd.DefDef )(using Context ): tpd.Tree = trace(i " transformDefDef $tree, ${tree.tpe}, ${tree.tpe.widen}" ){
145+ val tup : Tuple3 [Int , List [TypeB ], TypeB ] = tree.tpe.widen match
146+ case pt : PolyType => pt.resType match
102147 case mt : MethodType =>
103- val params = mt.paramInfos.map(p => toTypeB(p, sym))
104- val ret = toTypeB(mt.resType, sym)
105- if (params.exists(_ != TypeB .None ) || ret != TypeB .None ) then
106- sym.addAnnotation(ErasedInfo (0 , params, ret))
107- case et : ExprType =>
108- val ret = toTypeB(et.widenExpr, sym)
109- if (ret != TypeB .None ) then
110- sym.addAnnotation(ErasedInfo (0 , Nil , ret))
111- ()
148+ methodToInfos(mt.paramInfos, mt.resType, tree.symbol.paramSymss.head, tree.symbol.isConstructor)
112149 case other =>
113- tp
150+ methodToInfos(Nil , other.widenExpr, tree.symbol.paramSymss.head, tree.symbol.isConstructor)
151+ case mt : MethodType =>
152+ methodToInfos(mt.paramInfos, mt.resType, Nil , false )
153+ // case tr: TypeRef =>
154+ // methodToInfos(Nil, tr, Nil, false)
155+ // case et: ExprType =>
156+ // ???
157+ case other =>
158+ (0 , Nil , TypeB .None )
159+ val (paramCount, paramRefs, retType) = tup
160+ if (paramCount != 0 || paramRefs.length > 0 || retType != TypeB .None ) then
161+ tree.putAttachment(MethodParameterReturnType , (paramCount, paramRefs, retType))
162+ tree
114163 }
115164
116- override def transformApply (tree : tpd.Apply )(using Context ): tpd.Tree =
117- tree.putAttachment(InvokeReturnType , toReturnTypeB(tree.tpe, tree.symbol))
165+ override def transformApply (tree : tpd.Apply )(using Context ): tpd.Tree = trace(i " transfromApply ${tree}" ) {
166+ val outers = getOuterParamss(ctx.owner, false )
167+ tree.putAttachment(InvokeReturnType , toReturnTypeB(tree.tpe, outers))
118168 tree
169+ }
119170
120- override def transformTypeApply (tree : tpd.TypeApply )(using Context ): tpd.Tree =
121- val args = tree.args.map(_.tpe).map(p => toTypeA(p, tree.symbol))
122- tree.fun.putAttachment(InstructionTypeArguments , args) // Pattern match args based on their types
171+ override def transformTypeApply (tree : tpd.TypeApply )(using Context ): tpd.Tree = trace(i " transfromTypeApply ${tree}" ) {
172+ val outers = getOuterParamss(ctx.owner, false )
173+ val args = tree.args.map(_.tpe).map(p => toTypeA(p, outers))
174+ tree.fun.putAttachment(InstructionTypeArguments , args)
123175 tree
124-
125- // override def transformTypeDef(tree: tpd.TypeDef)(using Context): tpd.Tree =
126- // println(s"$tree")
127- // tree
176+ }
128177
129178}
130179
@@ -154,10 +203,12 @@ enum TypeB:
154203 case K (
155204 outer : Int ,
156205 paramNum : Int )
206+ case Array (tp : TypeB )
157207// case class TypeB(tp: Type)
158208
159209object InstructionTypeArguments extends Property .StickyKey [List [TypeA ]]
160210object InvokeReturnType extends Property .StickyKey [TypeB ]
211+ object MethodParameterReturnType extends Property .StickyKey [(Int , List [TypeB ], TypeB )]
161212
162213class ErasedInfo (val paramCount : Int , val paramType : List [TypeB ], val returnType : TypeB ) extends Annotation {
163214 override def tree (using Context ) =
0 commit comments