@@ -239,26 +239,44 @@ object Erasure {
239
239
* Casts from and to ErasedValueType are special, see the explanation
240
240
* in ExtensionMethods#transform.
241
241
*/
242
- def cast (tree : Tree , pt : Type )(implicit ctx : Context ): Tree = {
242
+ def cast (tree : Tree , pt : Type )(implicit ctx : Context ): Tree = ctx.traceIndented(i " cast ${tree.tpe.widen} --> $pt" , show = true ) {
243
+ def wrap (tycon : TypeRef ) =
244
+ ref(u2evt(tycon.typeSymbol.asClass)).appliedTo(tree)
245
+ def unwrap (tycon : TypeRef ) =
246
+ ref(evt2u(tycon.typeSymbol.asClass)).appliedTo(tree)
247
+
248
+
243
249
assert(! pt.isInstanceOf [SingletonType ], pt)
244
250
if (pt isRef defn.UnitClass ) unbox(tree, pt)
245
- else (tree.tpe, pt) match {
251
+ else (tree.tpe.widen , pt) match {
246
252
case (JavaArrayType (treeElem), JavaArrayType (ptElem))
247
253
if treeElem.widen.isPrimitiveValueType && ! ptElem.isPrimitiveValueType =>
248
254
// See SI-2386 for one example of when this might be necessary.
249
255
cast(ref(defn.runtimeMethodRef(nme.toObjectArray)).appliedTo(tree), pt)
250
- case (_, ErasedValueType (tycon, _)) =>
251
- ref(u2evt(tycon.symbol.asClass)).appliedTo(tree)
252
- case _ =>
253
- tree.tpe.widen match {
254
- case ErasedValueType (tycon, _) =>
255
- ref(evt2u(tycon.symbol.asClass)).appliedTo(tree )
256
- case _ =>
257
- if (pt.isPrimitiveValueType)
258
- primitiveConversion(tree, pt.classSymbol )
259
- else
260
- tree.asInstance(pt )
256
+
257
+ // When casting between two EVTs, we need to check which one underlies the other to determine
258
+ // wheter u2evt or evt2u should be used.
259
+ case (tp1 @ ErasedValueType (tycon1, underlying1), tp2 @ ErasedValueType (tycon2, underlying2)) =>
260
+ if (tp1 <:< underlying2)
261
+ // Cast EVT(tycon1, underlying1) to EVT(tycon2, EVT(tycon1, underlying1) )
262
+ wrap(tycon2)
263
+ else {
264
+ assert(underlying1 <:< tp2, i " Non-sensical cast between unrelated types $tp1 and $tp2 " )
265
+ // Cast EVT(tycon1, EVT(tycon2, underlying2)) to EVT(tycon2, underlying2)
266
+ unwrap(tycon1 )
261
267
}
268
+
269
+ // When only one type is an EVT then we already know that the other one is the underlying
270
+ case (_, ErasedValueType (tycon2, _)) =>
271
+ wrap(tycon2)
272
+ case (ErasedValueType (tycon1, _), _) =>
273
+ unwrap(tycon1)
274
+
275
+ case _ =>
276
+ if (pt.isPrimitiveValueType)
277
+ primitiveConversion(tree, pt.classSymbol)
278
+ else
279
+ tree.asInstance(pt)
262
280
}
263
281
}
264
282
0 commit comments