Skip to content

Commit 0f78b20

Browse files
committed
Insert correct boxing/unboxing conversions for branches
... of an If, Match, or Try. Fixes #355.
1 parent 92013ab commit 0f78b20

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,36 @@ object Erasure extends TypeTestsCasts{
252252
if (tree.typeOpt.isRef(defn.UnitClass)) tree.withType(tree.typeOpt)
253253
else super.typedLiteral(tree)
254254

255+
// The following methods, typedIf, typedMatch and typedTry need to compensate
256+
// for the fact that after erasure, a subtype may notbe compatible with the
257+
// type of a lub. Hence we might need to readapt branches to the common type.
258+
// Note that the typing of SeqLiteral faces a similar problem but solves it
259+
// differently: It adapts all elements to the erasure of the type that existed
260+
// before. TODO: It looks like a good idea to harmonize this.
261+
//
262+
override def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context): If = {
263+
val tree1 = super.typedIf(tree, pt)
264+
println(i"typed if $tree1 with $pt = ${tree1.tpe}")
265+
if (pt.isValueType) tree1
266+
else cpy.If(tree1)(thenp = adapt(tree1.thenp, tree1.tpe), elsep = adapt(tree1.elsep, tree1.tpe))
267+
}
268+
269+
override def typedMatch(tree: untpd.Match, pt: Type)(implicit ctx: Context): Match = {
270+
val tree1 = super.typedMatch(tree, pt).asInstanceOf[Match]
271+
if (pt.isValueType) tree1
272+
else cpy.Match(tree1)(tree1.selector, tree1.cases.map(adaptCase(_, tree1.tpe)))
273+
}
274+
275+
override def typedTry(tree: untpd.Try, pt: Type)(implicit ctx: Context): Try = {
276+
val tree1 = super.typedTry(tree, pt)
277+
if (pt.isValueType) tree1
278+
else cpy.Try(tree1)(expr = adapt(tree1.expr, tree1.tpe), cases = tree1.cases.map(adaptCase(_, tree1.tpe)))
279+
}
280+
281+
private def adaptCase(cdef: CaseDef, pt: Type)(implicit ctx: Context): CaseDef =
282+
cpy.CaseDef(cdef)(body = adapt(cdef.body, pt))
283+
284+
255285
/** Type check select nodes, applying the following rewritings exhaustively
256286
* on selections `e.m`, where `OT` is the type of the owner of `m` and `ET`
257287
* is the erased type of the selection's original qualifier expression.

tests/pos/erased-lub.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Verify that expressions below perform correct boxings in erasure.
2+
object Test {
3+
def id[T](t: T) = t
4+
5+
val x = true
6+
val one = 1
7+
8+
{ if (x) id(one) else 0 } + 1
9+
10+
{ if (x) new scala.util.Random()}.asInstanceOf[Runnable]
11+
12+
{ x match {
13+
case true => id(one)
14+
case _ => 0
15+
}
16+
} + 1
17+
18+
{ try {
19+
id(one)
20+
} catch {
21+
case ex: Exception => 0
22+
}
23+
}.asInstanceOf[Runnable]
24+
25+
val arr = Array(id(one), 0)
26+
27+
}

0 commit comments

Comments
 (0)