@@ -37,7 +37,7 @@ class Erasure extends Phase with DenotTransformer {
37
37
38
38
def run (implicit ctx : Context ): Unit = {
39
39
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))
41
41
}
42
42
}
43
43
@@ -53,8 +53,10 @@ object Erasure {
53
53
def isBox (sym : Symbol )(implicit ctx : Context ) =
54
54
sym.name == nme.box && (defn.ScalaValueClasses contains sym.owner)
55
55
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
58
60
59
61
/** Isf this tree is an unbox operation which can be safely removed
60
62
* when enclosed in a box, the unboxed argument, otherwise EmptyTree.
@@ -65,7 +67,7 @@ object Erasure {
65
67
*/
66
68
private def safelyRemovableUnboxArg (tree : Tree )(implicit ctx : Context ): Tree = tree match {
67
69
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) =>
69
71
arg
70
72
case _ =>
71
73
EmptyTree
@@ -78,11 +80,11 @@ object Erasure {
78
80
if (isIdempotentExpr(tree)) Block (tree :: Nil , const) else const
79
81
80
82
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 {
82
84
case ErasedValueType (clazz, _) =>
83
85
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
86
88
if (cls eq defn.UnitClass ) constant(tree, ref(defn.BoxedUnit_UNIT ))
87
89
else if (cls eq defn.NothingClass ) tree // a non-terminating expression doesn't need boxing
88
90
else {
@@ -124,7 +126,7 @@ object Erasure {
124
126
if (pt isRef defn.UnitClass ) unbox(tree, pt)
125
127
else (tree.tpe, pt) match {
126
128
case (defn.ArrayType (treeElem), defn.ArrayType (ptElem))
127
- if isPrimitiveValueType(treeElem) && ! isPrimitiveValueType(ptElem) =>
129
+ if isPrimitiveValueType(treeElem.widen ) && ! isPrimitiveValueType(ptElem) =>
128
130
// See SI-2386 for one example of when this might be necessary.
129
131
cast(runtimeCall(nme.toObjectArray, tree :: Nil ), pt)
130
132
case _ =>
@@ -144,13 +146,13 @@ object Erasure {
144
146
def adaptToType (tree : Tree , pt : Type )(implicit ctx : Context ): Tree =
145
147
if (tree.tpe <:< pt)
146
148
tree
147
- else if (isErasedValueType(tree.tpe))
149
+ else if (isErasedValueType(tree.tpe.widen ))
148
150
adaptToType(box(tree), pt)
149
151
else if (isErasedValueType(pt))
150
152
adaptToType(unbox(tree, pt), pt)
151
- else if (isPrimitiveValueType(tree.tpe) && ! isPrimitiveValueType(pt))
153
+ else if (isPrimitiveValueType(tree.tpe.widen ) && ! isPrimitiveValueType(pt))
152
154
adaptToType(box(tree), pt)
153
- else if (isPrimitiveValueType(pt) && ! isPrimitiveValueType(tree.tpe))
155
+ else if (isPrimitiveValueType(pt) && ! isPrimitiveValueType(tree.tpe.widen ))
154
156
adaptToType(unbox(tree, pt), pt)
155
157
else
156
158
cast(tree, pt)
@@ -159,14 +161,14 @@ object Erasure {
159
161
class Typer extends typer.Typer with NoChecking {
160
162
import Boxing ._
161
163
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 ])
165
166
166
167
private def promote (tree : untpd.Tree )(implicit ctx : Context ): tree.ThisTree [Type ] = {
167
168
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)
170
172
}
171
173
172
174
override def typedIdent (tree : untpd.Ident , pt : Type )(implicit ctx : Context ): Tree = {
@@ -244,7 +246,10 @@ object Erasure {
244
246
block // optimization, no checking needed, as block symbols do not change.
245
247
246
248
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)
248
253
super .typedDefDef(ddef1, sym)
249
254
}
250
255
@@ -280,7 +285,7 @@ object Erasure {
280
285
281
286
override def adapt (tree : Tree , pt : Type )(implicit ctx : Context ): Tree =
282
287
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 )
284
289
if (tree.isEmpty) tree else adaptToType(tree, pt)
285
290
}
286
291
}
0 commit comments