@@ -19,69 +19,113 @@ import ast.{tpd, untpd}
1919import reporting .*
2020import dotty .tools .dotc .transform .MegaPhase .MiniPhase
2121import dotty .tools .dotc .util .Property
22+ import dotty .tools .dotc .cc .pathOwner
23+ import scala .annotation .tailrec
2224
2325class ErasurePreservation extends MiniPhase with InfoTransformer {
2426
2527 override def phaseName : String = ErasurePreservation .name
2628
2729 override def description : String = ErasurePreservation .description
2830
29- def toTypeA (tp : Type )(using Context ): TypeA = trace(s " toTypeA ${tp}" ) {tp match
31+ def toTypeA (tp : Type , sourceSym : Symbol )(using Context ): TypeA = trace(s " toTypeA ${tp}" ) {tp match
3032 case tpr : TypeParamRef => TypeA .M (tpr.paramNum)
3133 case tr : TypeRef =>
3234 // println(tr.symbol.owner.paramSymss)
3335 if tr.isRef(defn.ByteClass ) then TypeA .Byte else
3436 if tr.isRef(defn.CharClass ) then TypeA .Char else
35- if tr.isRef(defn.DoubleClass ) then TypeA .Double else
36- if tr.isRef(defn.FloatClass ) then TypeA .Float else
37+ if tr.isRef(defn.DoubleClass ) then TypeA .Double else
38+ if tr.isRef(defn.FloatClass ) then TypeA .Float else
3739 if tr.isRef(defn.IntClass ) then TypeA .Int else
38- if tr.isRef(defn.LongClass ) then TypeA .Long else
40+ if tr.isRef(defn.LongClass ) then TypeA .Long else
3941 if tr.isRef(defn.ShortClass ) then TypeA .Short else
40- if tr.isRef(defn.BooleanClass ) then TypeA .Boolean else
42+ if tr.isRef(defn.BooleanClass ) then TypeA .Boolean else
4143 if tr.symbol.isTypeParam then
42- val ind = tr.symbol.owner.paramSymss.head.indexWhere(tr.isRef(_))
43- if ind != - 1 then TypeA .M (ind)
44- else TypeA .Ref
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 ???
4554 else TypeA .Ref
4655 case _ => assert(false )
4756 }
4857
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+ }
4962
50- def toTypeB (tp : Type )(using Context ): TypeB = tp match
63+ def toTypeB (tp : Type , sourceSym : Symbol )(using Context ): TypeB = trace( i " toTypeB ${tp} " ){ tp match
5164 case tpr : TypeParamRef => TypeB .M (tpr.paramNum)
65+ 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
5276 case _ => TypeB .None
77+ }
5378
54- def toReturnTypeB (tp : Type )(using Context ): TypeB = tp match
55- case tr : TypeRef =>
56- // println(tr.symbol.owner.paramSymss)
57- if tr.symbol.isTypeParam then
58- val ind = tr.symbol.owner.paramSymss.head.indexWhere(tr.isRef(_))
59- if ind != - 1 then TypeB .M (ind)
60- else TypeB .None
61- else TypeB .None
79+ def toReturnTypeB (tp : Type , sourceSym : Symbol )(using Context ): TypeB = tp match
80+ 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
6291 case _ => TypeB .None
6392
64-
65- override def transformInfo (tp : Type , sym : Symbol )(using Context ): Type =
93+ override def transformInfo (tp : Type , sym : Symbol )(using Context ): Type = trace(i " transformInfo ${tp}, ${sym}" ) {
6694 tp match
6795 case pt : PolyType =>
6896 pt.resType match
6997 case mt : MethodType =>
70- sym.addAnnotation(ErasedInfo (pt.paramInfos.size, mt.paramInfos.map(toTypeB), toTypeB(mt.resType)))
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)))
71100 case other =>
72- sym.addAnnotation(ErasedInfo (pt.paramInfos.size, Nil , toTypeB(other.widenExpr)))
73- case _ => ()
101+ sym.addAnnotation(ErasedInfo (pt.paramInfos.size, Nil , toTypeB(other.widenExpr, sym)))
102+ 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+ ()
112+ case other =>
74113 tp
114+ }
75115
76116 override def transformApply (tree : tpd.Apply )(using Context ): tpd.Tree =
77- tree.putAttachment(InvokeReturnType , toReturnTypeB(tree.tpe))
117+ tree.putAttachment(InvokeReturnType , toReturnTypeB(tree.tpe, tree.symbol ))
78118 tree
79119
80120 override def transformTypeApply (tree : tpd.TypeApply )(using Context ): tpd.Tree =
81- val args = tree.args.map(_.tpe).map(toTypeA)
121+ val args = tree.args.map(_.tpe).map(p => toTypeA(p, tree.symbol) )
82122 tree.fun.putAttachment(InstructionTypeArguments , args) // Pattern match args based on their types
83123 tree
84124
125+ // override def transformTypeDef(tree: tpd.TypeDef)(using Context): tpd.Tree =
126+ // println(s"$tree")
127+ // tree
128+
85129}
86130
87131object ErasurePreservation {
@@ -98,14 +142,18 @@ enum TypeA:
98142 case Long
99143 case Short
100144 case Boolean
101- case M (x : Int )
102- case K (y : Int , x : Int )
145+ case M (paramNum : Int )
146+ case K (
147+ outer : Int ,
148+ paramNum : Int )
103149 case Ref
104150
105151enum TypeB :
106152 case None
107- case M (x : Int )
108- case K (y : Int , x : Int )
153+ case M (paramNum : Int )
154+ case K (
155+ outer : Int ,
156+ paramNum : Int )
109157// case class TypeB(tp: Type)
110158
111159object InstructionTypeArguments extends Property .StickyKey [List [TypeA ]]
0 commit comments