@@ -1263,50 +1263,81 @@ impl Evaluator<'_> {
1263
1263
current_ty : & Ty ,
1264
1264
target_ty : & Ty ,
1265
1265
) -> Result < IntervalOrOwned > {
1266
- use IntervalOrOwned :: * ;
1267
1266
fn for_ptr ( x : & TyKind ) -> Option < Ty > {
1268
1267
match x {
1269
1268
TyKind :: Raw ( _, ty) | TyKind :: Ref ( _, _, ty) => Some ( ty. clone ( ) ) ,
1270
1269
_ => None ,
1271
1270
}
1272
1271
}
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)
1296
1300
}
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" ) ;
1305
1317
}
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" ) ,
1309
1339
} ,
1340
+ _ => not_supported ! ( "unknown unsized cast" ) ,
1310
1341
} )
1311
1342
}
1312
1343
0 commit comments