@@ -1263,50 +1263,81 @@ impl Evaluator<'_> {
12631263 current_ty : & Ty ,
12641264 target_ty : & Ty ,
12651265 ) -> Result < IntervalOrOwned > {
1266- use IntervalOrOwned :: * ;
12671266 fn for_ptr ( x : & TyKind ) -> Option < Ty > {
12681267 match x {
12691268 TyKind :: Raw ( _, ty) | TyKind :: Ref ( _, _, ty) => Some ( ty. clone ( ) ) ,
12701269 _ => None ,
12711270 }
12721271 }
1273- Ok ( match self . coerce_unsized_look_through_fields ( target_ty, for_ptr) ? {
1274- ty => match & ty. data ( Interner ) . kind {
1275- TyKind :: Slice ( _) => {
1276- match self . coerce_unsized_look_through_fields ( current_ty, for_ptr) ? {
1277- ty => match & ty. data ( Interner ) . kind {
1278- TyKind :: Array ( _, size) => {
1279- let len = match try_const_usize ( self . db , size) {
1280- None => not_supported ! (
1281- "unevaluatble len of array in coerce unsized"
1282- ) ,
1283- Some ( x) => x as usize ,
1284- } ;
1285- let mut r = Vec :: with_capacity ( 16 ) ;
1286- let addr = addr. get ( self ) ?;
1287- r. extend ( addr. iter ( ) . copied ( ) ) ;
1288- r. extend ( len. to_le_bytes ( ) . into_iter ( ) ) ;
1289- Owned ( r)
1290- }
1291- t => {
1292- not_supported ! ( "slice unsizing from non array type {t:?}" )
1293- }
1294- } ,
1295- }
1272+ let target_ty = self . coerce_unsized_look_through_fields ( target_ty, for_ptr) ?;
1273+ let current_ty = self . coerce_unsized_look_through_fields ( current_ty, for_ptr) ?;
1274+
1275+ self . unsizing_ptr_from_addr ( target_ty, current_ty, addr)
1276+ }
1277+
1278+ /// Adds metadata to the address and create the fat pointer result of the unsizing operation.
1279+ fn unsizing_ptr_from_addr (
1280+ & mut self ,
1281+ target_ty : Ty ,
1282+ current_ty : Ty ,
1283+ addr : Interval ,
1284+ ) -> Result < IntervalOrOwned > {
1285+ use IntervalOrOwned :: * ;
1286+ Ok ( match & target_ty. data ( Interner ) . kind {
1287+ TyKind :: Slice ( _) => match & current_ty. data ( Interner ) . kind {
1288+ TyKind :: Array ( _, size) => {
1289+ let len = match try_const_usize ( self . db , size) {
1290+ None => {
1291+ not_supported ! ( "unevaluatble len of array in coerce unsized" )
1292+ }
1293+ Some ( x) => x as usize ,
1294+ } ;
1295+ let mut r = Vec :: with_capacity ( 16 ) ;
1296+ let addr = addr. get ( self ) ?;
1297+ r. extend ( addr. iter ( ) . copied ( ) ) ;
1298+ r. extend ( len. to_le_bytes ( ) . into_iter ( ) ) ;
1299+ Owned ( r)
12961300 }
1297- TyKind :: Dyn ( _) => match & current_ty. data ( Interner ) . kind {
1298- TyKind :: Raw ( _, ty) | TyKind :: Ref ( _, _, ty) => {
1299- let vtable = self . vtable_map . id ( ty. clone ( ) ) ;
1300- let mut r = Vec :: with_capacity ( 16 ) ;
1301- let addr = addr. get ( self ) ?;
1302- r. extend ( addr. iter ( ) . copied ( ) ) ;
1303- r. extend ( vtable. to_le_bytes ( ) . into_iter ( ) ) ;
1304- Owned ( r)
1301+ t => {
1302+ not_supported ! ( "slice unsizing from non array type {t:?}" )
1303+ }
1304+ } ,
1305+ TyKind :: Dyn ( _) => {
1306+ let vtable = self . vtable_map . id ( current_ty. clone ( ) ) ;
1307+ let mut r = Vec :: with_capacity ( 16 ) ;
1308+ let addr = addr. get ( self ) ?;
1309+ r. extend ( addr. iter ( ) . copied ( ) ) ;
1310+ r. extend ( vtable. to_le_bytes ( ) . into_iter ( ) ) ;
1311+ Owned ( r)
1312+ }
1313+ TyKind :: Adt ( id, target_subst) => match & current_ty. data ( Interner ) . kind {
1314+ TyKind :: Adt ( current_id, current_subst) => {
1315+ if id != current_id {
1316+ not_supported ! ( "unsizing struct with different type" ) ;
13051317 }
1306- _ => not_supported ! ( "dyn unsizing from non pointers" ) ,
1307- } ,
1308- _ => not_supported ! ( "unknown unsized cast" ) ,
1318+ let id = match id. 0 {
1319+ AdtId :: StructId ( s) => s,
1320+ AdtId :: UnionId ( _) => not_supported ! ( "unsizing unions" ) ,
1321+ AdtId :: EnumId ( _) => not_supported ! ( "unsizing enums" ) ,
1322+ } ;
1323+ let Some ( ( last_field, _) ) = self . db . struct_data ( id) . variant_data . fields ( ) . iter ( ) . rev ( ) . next ( ) else {
1324+ not_supported ! ( "unsizing struct without field" ) ;
1325+ } ;
1326+ let target_last_field = self . db . field_types ( id. into ( ) ) [ last_field]
1327+ . clone ( )
1328+ . substitute ( Interner , target_subst) ;
1329+ let current_last_field = self . db . field_types ( id. into ( ) ) [ last_field]
1330+ . clone ( )
1331+ . substitute ( Interner , current_subst) ;
1332+ return self . unsizing_ptr_from_addr (
1333+ target_last_field,
1334+ current_last_field,
1335+ addr,
1336+ ) ;
1337+ }
1338+ _ => not_supported ! ( "unsizing struct with non adt type" ) ,
13091339 } ,
1340+ _ => not_supported ! ( "unknown unsized cast" ) ,
13101341 } )
13111342 }
13121343
0 commit comments