@@ -410,21 +410,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
410
410
self . unsize_into_ptr ( src, dest, * s, * c)
411
411
}
412
412
( & ty:: Adt ( def_a, _) , & ty:: Adt ( def_b, _) ) => {
413
- assert_eq ! ( def_a, def_b) ;
413
+ assert_eq ! ( def_a, def_b) ; // implies same number of fields
414
414
415
- // unsizing of generic struct with pointer fields
416
- // Example: `Arc<T>` -> `Arc<Trait>`
417
- // here we need to increase the size of every &T thin ptr field to a fat ptr
415
+ // Unsizing of generic struct with pointer fields, like `Arc<T>` -> `Arc<Trait>`.
416
+ // There can be extra fields as long as they don't change their type or are 1-ZST.
417
+ // There might also be no field that actually needs unsizing.
418
+ let mut found_cast_field = false ;
418
419
for i in 0 ..src. layout . fields . count ( ) {
419
420
let cast_ty_field = cast_ty. field ( self , i) ;
420
- if cast_ty_field. is_zst ( ) {
421
- continue ;
422
- }
423
421
let src_field = self . project_field ( src, i) ?;
424
422
let dst_field = self . project_field ( dest, i) ?;
425
- if src_field. layout . ty == cast_ty_field. ty {
423
+ if src_field. layout . is_1zst ( ) && cast_ty_field. is_1zst ( ) {
424
+ // Skip 1-ZST fields.
425
+ } else if src_field. layout . ty == cast_ty_field. ty {
426
426
self . copy_op ( & src_field, & dst_field, /*allow_transmute*/ false ) ?;
427
427
} else {
428
+ if found_cast_field {
429
+ span_bug ! ( self . cur_span( ) , "unsize_into: more than one field to cast" ) ;
430
+ }
431
+ found_cast_field = true ;
428
432
self . unsize_into ( & src_field, cast_ty_field, & dst_field) ?;
429
433
}
430
434
}
0 commit comments