@@ -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