@@ -239,26 +239,44 @@ object Erasure {
239239 * Casts from and to ErasedValueType are special, see the explanation
240240 * in ExtensionMethods#transform.
241241 */
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+
243249 assert(! pt.isInstanceOf [SingletonType ], pt)
244250 if (pt isRef defn.UnitClass ) unbox(tree, pt)
245- else (tree.tpe, pt) match {
251+ else (tree.tpe.widen , pt) match {
246252 case (JavaArrayType (treeElem), JavaArrayType (ptElem))
247253 if treeElem.widen.isPrimitiveValueType && ! ptElem.isPrimitiveValueType =>
248254 // See SI-2386 for one example of when this might be necessary.
249255 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 )
261267 }
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)
262280 }
263281 }
264282
0 commit comments