Skip to content

Commit 5f715d9

Browse files
committed
Merge branch erasure-annot into insertAttr; modified TypeHints
2 parents 5d7faed + ad15054 commit 5f715d9

File tree

9 files changed

+169
-85
lines changed

9 files changed

+169
-85
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeHelpers.scala

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,12 @@ trait BCodeHelpers extends BCodeIdiomatic {
226226
tpe match
227227
case dotty.tools.dotc.transform.TypeB.None => TypeHints.TypeB.NO_HINT
228228
case dotty.tools.dotc.transform.TypeB.M(index) => new TypeHints.TypeB(TypeHints.TypeB.M_KIND, index)
229-
case dotty.tools.dotc.transform.TypeB.K(y, x) => new TypeHints.TypeB(TypeHints.TypeB.K_KIND, y, x)
229+
case dotty.tools.dotc.transform.TypeB.K(outer, index) => new TypeHints.TypeB(TypeHints.TypeB.K_KIND, outer, index)
230+
case dotty.tools.dotc.transform.TypeB.Array(dotty.tools.dotc.transform.TypeB.K(outer, index)) => new TypeHints.TypeB(TypeHints.TypeB.ARR_K_KIND, outer, index)
231+
case dotty.tools.dotc.transform.TypeB.Array(dotty.tools.dotc.transform.TypeB.M(index)) => new TypeHints.TypeB(TypeHints.TypeB.ARR_M_KIND, index)
232+
case _ =>
233+
report.error("unexpected type in to Java TypeB: " + tpe)
234+
TypeHints.TypeB.NO_HINT // fallback, should not happen
230235

231236
def addMethodTypeParameterCountAttribute(mw: asm.MethodVisitor, count: Int): Unit =
232237
if (count > 0){
@@ -237,17 +242,15 @@ trait BCodeHelpers extends BCodeIdiomatic {
237242
def addMethodReturnTypeAttribute(mw: asm.MethodVisitor, tpe: dotty.tools.dotc.transform.TypeB): Unit =
238243
val typeB =
239244
tpe match
240-
case dotty.tools.dotc.transform.TypeB.K(outerClassIndex, index) =>
241-
new TypeHints.TypeB(TypeHints.TypeB.K_KIND, outerClassIndex, index)
242-
case dotty.tools.dotc.transform.TypeB.M(index) =>
243-
new TypeHints.TypeB(TypeHints.TypeB.M_KIND, index)
244-
case dotty.tools.dotc.transform.TypeB.None => TypeHints.TypeB.NO_HINT//do nothing
245+
case dotty.tools.dotc.transform.TypeB.K(outerClassIndex, index) => new TypeHints.TypeB(TypeHints.TypeB.K_KIND, outerClassIndex, index)
246+
case dotty.tools.dotc.transform.TypeB.M(index) => new TypeHints.TypeB(TypeHints.TypeB.M_KIND, index)
247+
case dotty.tools.dotc.transform.TypeB.Array(dotty.tools.dotc.transform.TypeB.K(outerClassIndex, index)) => new TypeHints.TypeB(TypeHints.TypeB.ARR_K_KIND, outerClassIndex, index)
248+
case dotty.tools.dotc.transform.TypeB.Array(dotty.tools.dotc.transform.TypeB.M(index)) => new TypeHints.TypeB(TypeHints.TypeB.ARR_M_KIND, index)
249+
case _ => TypeHints.TypeB.NO_HINT//do nothing
245250
if (typeB != TypeHints.TypeB.NO_HINT) {
246251
val attr = new MethodReturnType(typeB)
247252
mw.visitAttribute(attr)
248253
}
249-
250-
251254

252255
def addMethodParameterTypeAttribute(mw: asm.MethodVisitor, lst: List[dotty.tools.dotc.transform.TypeB]) : Unit =
253256
if (lst.isEmpty) return

compiler/src/dotty/tools/backend/jvm/BCodeIdiomatic.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,10 @@ trait BCodeIdiomatic {
430430
tpe match
431431
case dotty.tools.dotc.transform.TypeB.None => TypeHints.TypeB.NO_HINT
432432
case dotty.tools.dotc.transform.TypeB.M(index) => new TypeHints.TypeB(TypeHints.TypeB.M_KIND, index)
433-
case dotty.tools.dotc.transform.TypeB.K(y, x) => new TypeHints.TypeB(TypeHints.TypeB.K_KIND, y, x)
433+
case dotty.tools.dotc.transform.TypeB.K(outer, index) => new TypeHints.TypeB(TypeHints.TypeB.K_KIND, outer, index)
434+
case dotty.tools.dotc.transform.TypeB.Array(dotty.tools.dotc.transform.TypeB.K(outer, index)) => new TypeHints.TypeB(TypeHints.TypeB.ARR_K_KIND, outer, index)
435+
case dotty.tools.dotc.transform.TypeB.Array(dotty.tools.dotc.transform.TypeB.M(index)) => new TypeHints.TypeB(TypeHints.TypeB.ARR_M_KIND, index)
436+
case _ => TypeHints.TypeB.NO_HINT
434437

435438
def toJTypeA(tpe: dotty.tools.dotc.transform.TypeA): TypeHints.TypeA =
436439
tpe match

compiler/src/dotty/tools/backend/jvm/attributes/TypeHints.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public TypeA(byte kind, int index) {
4848
}
4949

5050
public TypeA(byte kind, int outerClassIndex, int index) {
51+
assert kind == K_KIND;
5152
this.kind = kind;
5253
this.outerClassIndex = outerClassIndex;
5354
this.index = index;
@@ -119,6 +120,7 @@ public TypeB(byte kind, int index) {
119120
}
120121

121122
public TypeB(byte kind, int outerClassIndex, int index) {
123+
assert kind == K_KIND || kind == ARR_K_KIND;
122124
this.kind = kind;
123125
this.outerClassIndex = outerClassIndex;
124126
this.index = index;

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,7 @@ class Definitions {
11001100
@tu lazy val RetainsArgAnnot: ClassSymbol = requiredClass("scala.annotation.retainsArg")
11011101
@tu lazy val PublicInBinaryAnnot: ClassSymbol = requiredClass("scala.annotation.publicInBinary")
11021102
@tu lazy val WitnessNamesAnnot: ClassSymbol = requiredClass("scala.annotation.internal.WitnessNames")
1103-
@tu lazy val ErasurePreservationAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ErasurePreservation")
1103+
@tu lazy val ErasurePreservationAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ErasurePreservationAnnot")
11041104

11051105
@tu lazy val JavaRepeatableAnnot: ClassSymbol = requiredClass("java.lang.annotation.Repeatable")
11061106

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import dotty.tools.dotc.parsing.JavaParsers
3737
import dotty.tools.dotc.transform.TreeExtractors.BinaryOp
3838
import dotty.tools.dotc.transform.InstructionTypeArguments
3939
import dotty.tools.dotc.transform.InvokeReturnType
40+
import dotty.tools.dotc.transform.MethodParameterReturnType
4041

4142
class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
4243

@@ -468,6 +469,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
468469

469470
(if tree.hasAttachment(InvokeReturnType) then Str("InvokeReturnType("+tree.attachment(InvokeReturnType).toString + ") ") else Str("")) ~
470471
(if tree.hasAttachment(InstructionTypeArguments) then Str("InstructionTypeArguments("+tree.attachment(InstructionTypeArguments).toString + ") ") else Str("")) ~
472+
(if tree.hasAttachment(MethodParameterReturnType) then Str("MethodParameterReturnType("+tree.attachment(MethodParameterReturnType).toString + ") ") else Str("")) ~
471473
(tree match {
472474
case id: Trees.SearchFailureIdent[?] =>
473475
tree.typeOpt match {

compiler/src/dotty/tools/dotc/transform/ErasurePreservation.scala

Lines changed: 119 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ import dotty.tools.dotc.util.Property
2222
import dotty.tools.dotc.cc.pathOwner
2323
import 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

159209
object InstructionTypeArguments extends Property.StickyKey[List[TypeA]]
160210
object InvokeReturnType extends Property.StickyKey[TypeB]
211+
object MethodParameterReturnType extends Property.StickyKey[(Int, List[TypeB], TypeB)]
161212

162213
class ErasedInfo(val paramCount: Int, val paramType: List[TypeB], val returnType: TypeB) extends Annotation {
163214
override def tree(using Context) =

library/src/scala/annotation/internal/ErasurePreservation.scala

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package scala.annotation.internal
2+
3+
import scala.annotation.Annotation
4+
import scala.annotation.meta.*
5+
6+
@getter
7+
@setter
8+
@field
9+
@param
10+
class ErasurePreservationAnnot(path: String) extends Annotation {
11+
12+
}

run-community-tests.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash
2+
PROJECTS=`cat community-build/test/scala/dotty/communitybuild/CommunityBuildTest.scala | grep '^[ ]*@Test' | sed 's/.* def //g' | sed 's/ = projects.*//g'`
3+
4+
RESULTS_DIR=/tmp/comm-build-results
5+
6+
mkdir -p $RESULTS_DIR
7+
echo "Found projects: $PROJECTS"
8+
echo "Results will be stored in: $RESULTS_DIR"
9+
10+
for PROJECT in $PROJECTS; do
11+
echo "Starting build for project: $PROJECT"
12+
CMD="community-build/testOnly -- *$PROJECT"
13+
echo "Running: sbt \"$CMD\" 2>&1 | tee $RESULTS_DIR/$PROJECT.log"
14+
sbt "$CMD" 2>&1 | tee $RESULTS_DIR/$PROJECT.log
15+
echo "Completed project: $PROJECT (exit code: $?)"
16+
echo "----------------------------------------"
17+
done
18+
echo "All builds completed!"

0 commit comments

Comments
 (0)