Skip to content

Commit d26d189

Browse files
oderskyDarkDimius
authored andcommitted
Fixes to erasure
Various fixes to the tree transformer. In the denotation transformer we now keep self types around because otherwise sourceModule would stop to work. Conflicts: src/dotty/tools/dotc/core/transform/Erasure.scala
1 parent e8748e2 commit d26d189

File tree

5 files changed

+41
-21
lines changed

5 files changed

+41
-21
lines changed

src/dotty/tools/dotc/Run.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class Run(comp: Compiler)(implicit ctx: Context) {
4141
phase.runOn(units)
4242
if (ctx.settings.Xprint.value.containsPhase(phase))
4343
for (unit <- units)
44-
printTree(ctx.fresh.withNewPhase(phase).withCompilationUnit(unit))
44+
printTree(ctx.fresh.setPhase(phase).setCompilationUnit(unit))
4545
}
4646
}
4747
}

src/dotty/tools/dotc/core/transform/Erasure.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ class Erasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcard
151151
if ((cls eq defn.ObjectClass) || cls.isPrimitiveValueClass) Nil
152152
else if (cls eq defn.ArrayClass) defn.ObjectClass.typeRef :: Nil
153153
else removeLaterObjects(classParents.mapConserve(eraseTypeRef))
154-
tp.derivedClassInfo(this(pre), parents, NoType)
154+
tp.derivedClassInfo(this(pre), parents, this(tp.selfType))
155155
case NoType | NoPrefix | ErrorType =>
156156
tp
157157
case tp: WildcardType if wildcardOK =>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
112112
case tp: ViewProto =>
113113
return toText(tp.argType) ~ " ?=>? " ~ toText(tp.resultType)
114114
case tp: TypeRef =>
115-
if (tp.symbol is TypeParam | TypeArgument) {
115+
if ((tp.symbol is TypeParam | TypeArgument) && !ctx.phase.erasedTypes) {
116116
return tp.info match {
117117
case TypeAlias(hi) => toText(hi)
118118
case _ => nameString(tp.symbol)

src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class Erasure extends Phase with DenotTransformer {
3737

3838
def run(implicit ctx: Context): Unit = {
3939
val unit = ctx.compilationUnit
40-
unit.tpdTree = eraser.typedExpr(unit.tpdTree)(ctx.fresh.withPhase(this.next))
40+
unit.tpdTree = eraser.typedExpr(unit.tpdTree)(ctx.fresh.setPhase(this.next))
4141
}
4242
}
4343

@@ -53,8 +53,10 @@ object Erasure {
5353
def isBox(sym: Symbol)(implicit ctx: Context) =
5454
sym.name == nme.box && (defn.ScalaValueClasses contains sym.owner)
5555

56-
def boxMethod(cls: ClassSymbol)(implicit ctx: Context) = cls.info.member(nme.box).symbol
57-
def unboxMethod(cls: ClassSymbol)(implicit ctx: Context) = cls.info.member(nme.unbox).symbol
56+
def boxMethod(cls: ClassSymbol)(implicit ctx: Context) =
57+
cls.linkedClass.info.member(nme.box).symbol
58+
def unboxMethod(cls: ClassSymbol)(implicit ctx: Context) =
59+
cls.linkedClass.info.member(nme.unbox).symbol
5860

5961
/** Isf this tree is an unbox operation which can be safely removed
6062
* when enclosed in a box, the unboxed argument, otherwise EmptyTree.
@@ -65,7 +67,7 @@ object Erasure {
6567
*/
6668
private def safelyRemovableUnboxArg(tree: Tree)(implicit ctx: Context): Tree = tree match {
6769
case Apply(fn, arg :: Nil)
68-
if isUnbox(fn.symbol) && (defn.ScalaBoxedClasses contains arg.tpe.typeSymbol) =>
70+
if isUnbox(fn.symbol) && (defn.ScalaBoxedClasses contains arg.tpe.widen.typeSymbol) =>
6971
arg
7072
case _ =>
7173
EmptyTree
@@ -78,11 +80,11 @@ object Erasure {
7880
if (isIdempotentExpr(tree)) Block(tree :: Nil, const) else const
7981

8082
final def box(tree: Tree, target: => String = "")(implicit ctx: Context): Tree = ctx.traceIndented(i"boxing ${tree.showSummary}: ${tree.tpe} into $target") {
81-
tree.tpe match {
83+
tree.tpe.widen match {
8284
case ErasedValueType(clazz, _) =>
8385
New(clazz.typeRef, cast(tree, clazz.underlyingOfValueClass) :: Nil) // todo: use adaptToType?
84-
case _ =>
85-
val cls = tree.tpe.classSymbol
86+
case tp =>
87+
val cls = tp.classSymbol
8688
if (cls eq defn.UnitClass) constant(tree, ref(defn.BoxedUnit_UNIT))
8789
else if (cls eq defn.NothingClass) tree // a non-terminating expression doesn't need boxing
8890
else {
@@ -124,7 +126,7 @@ object Erasure {
124126
if (pt isRef defn.UnitClass) unbox(tree, pt)
125127
else (tree.tpe, pt) match {
126128
case (defn.ArrayType(treeElem), defn.ArrayType(ptElem))
127-
if isPrimitiveValueType(treeElem) && !isPrimitiveValueType(ptElem) =>
129+
if isPrimitiveValueType(treeElem.widen) && !isPrimitiveValueType(ptElem) =>
128130
// See SI-2386 for one example of when this might be necessary.
129131
cast(runtimeCall(nme.toObjectArray, tree :: Nil), pt)
130132
case _ =>
@@ -144,13 +146,13 @@ object Erasure {
144146
def adaptToType(tree: Tree, pt: Type)(implicit ctx: Context): Tree =
145147
if (tree.tpe <:< pt)
146148
tree
147-
else if (isErasedValueType(tree.tpe))
149+
else if (isErasedValueType(tree.tpe.widen))
148150
adaptToType(box(tree), pt)
149151
else if (isErasedValueType(pt))
150152
adaptToType(unbox(tree, pt), pt)
151-
else if (isPrimitiveValueType(tree.tpe) && !isPrimitiveValueType(pt))
153+
else if (isPrimitiveValueType(tree.tpe.widen) && !isPrimitiveValueType(pt))
152154
adaptToType(box(tree), pt)
153-
else if (isPrimitiveValueType(pt) && !isPrimitiveValueType(tree.tpe))
155+
else if (isPrimitiveValueType(pt) && !isPrimitiveValueType(tree.tpe.widen))
154156
adaptToType(unbox(tree, pt), pt)
155157
else
156158
cast(tree, pt)
@@ -159,14 +161,14 @@ object Erasure {
159161
class Typer extends typer.Typer with NoChecking {
160162
import Boxing._
161163

162-
def box(tree: Tree): Tree = ???
163-
def unbox(tree: Tree, target: Type): Tree = ???
164-
def cast(tree: Tree, target: Type): Tree = ???
164+
def erasedType(tree: untpd.Tree)(implicit ctx: Context): Type =
165+
erasure(tree.tpe.asInstanceOf[Type])
165166

166167
private def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = {
167168
assert(tree.hasType)
168-
println(s"prompting ${tree.show}: ${tree.tpe.asInstanceOf[Type].showWithUnderlying(2)}")
169-
tree.withType(erasure(tree.tpe.asInstanceOf[Type]))
169+
val erased = erasedType(tree)(ctx.withPhase(ctx.erasurePhase))
170+
ctx.log(s"promoting ${tree.show}: ${erased.showWithUnderlying()}")
171+
tree.withType(erased)
170172
}
171173

172174
override def typedIdent(tree: untpd.Ident, pt: Type)(implicit ctx: Context): Tree = {
@@ -244,7 +246,10 @@ object Erasure {
244246
block // optimization, no checking needed, as block symbols do not change.
245247

246248
override def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context) = {
247-
val ddef1 = untpd.cpy.DefDef(ddef, ddef.mods, ddef.name, Nil, ddef.vparamss, ddef.tpt, ddef.rhs)
249+
val tpt1 = // keep UnitTypes intact in result position
250+
if (ddef.tpt.typeOpt isRef defn.UnitClass) untpd.TypeTree(defn.UnitType) withPos ddef.tpt.pos
251+
else ddef.tpt
252+
val ddef1 = untpd.cpy.DefDef(ddef, ddef.mods, ddef.name, Nil, ddef.vparamss, tpt1, ddef.rhs)
248253
super.typedDefDef(ddef1, sym)
249254
}
250255

@@ -280,7 +285,7 @@ object Erasure {
280285

281286
override def adapt(tree: Tree, pt: Type)(implicit ctx: Context): Tree =
282287
ctx.traceIndented(i"adapting ${tree.showSummary}: ${tree.tpe} to $pt", show = true) {
283-
assert(ctx.phase == ctx.erasurePhase.next)
288+
assert(ctx.phase == ctx.erasurePhase.next, ctx.phase)
284289
if (tree.isEmpty) tree else adaptToType(tree, pt)
285290
}
286291
}

tests/pos/erasure.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
object erasure {
2+
3+
class C(x: Int) {
4+
5+
def this() = this(0)
6+
}
7+
8+
import java.lang._
9+
10+
def const[T](x: T, y: T) = x
11+
12+
val x = 2
13+
val y = const(x, 3)
14+
15+
}

0 commit comments

Comments
 (0)