@@ -410,21 +410,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
410410 self . unsize_into_ptr ( src, dest, * s, * c)
411411 }
412412 ( & 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
414414
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 ;
418419 for i in 0 ..src. layout . fields . count ( ) {
419420 let cast_ty_field = cast_ty. field ( self , i) ;
420- if cast_ty_field. is_zst ( ) {
421- continue ;
422- }
423421 let src_field = self . project_field ( src, i) ?;
424422 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 {
426426 self . copy_op ( & src_field, & dst_field, /*allow_transmute*/ false ) ?;
427427 } 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 ;
428432 self . unsize_into ( & src_field, cast_ty_field, & dst_field) ?;
429433 }
430434 }
0 commit comments