@@ -2523,41 +2523,57 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2523
2523
ty:: lookup_field_type_unsubstituted ( tcx, def_id, f. id )
2524
2524
} ) . collect :: < Vec < _ > > ( ) ;
2525
2525
2526
- // FIXME(#25351) The last field of the structure has to exist and be a
2527
- // type parameter (for now, to avoid tracking edge cases).
2528
- let i = if let Some ( & ty:: ty_param( p) ) = fields. last ( ) . map ( |ty| & ty. sty ) {
2529
- assert ! ( p. space == TypeSpace ) ;
2530
- p. idx as usize
2526
+ // The last field of the structure has to exist and contain type parameters.
2527
+ let field = if let Some ( & field) = fields. last ( ) {
2528
+ field
2531
2529
} else {
2532
2530
return Err ( Unimplemented ) ;
2533
2531
} ;
2532
+ let mut ty_params = vec ! [ ] ;
2533
+ ty:: walk_ty ( field, |ty| {
2534
+ if let ty:: ty_param( p) = ty. sty {
2535
+ assert ! ( p. space == TypeSpace ) ;
2536
+ let idx = p. idx as usize ;
2537
+ if !ty_params. contains ( & idx) {
2538
+ ty_params. push ( idx) ;
2539
+ }
2540
+ }
2541
+ } ) ;
2542
+ if ty_params. is_empty ( ) {
2543
+ return Err ( Unimplemented ) ;
2544
+ }
2534
2545
2535
- // Replace the type parameter chosen for unsizing with
2536
- // ty_err and ensure it does not affect any other fields.
2546
+ // Replace type parameters used in unsizing with
2547
+ // ty_err and ensure they do not affect any other fields.
2537
2548
// This could be checked after type collection for any struct
2538
2549
// with a potentially unsized trailing field.
2539
2550
let mut new_substs = substs_a. clone ( ) ;
2540
- new_substs. types . get_mut_slice ( TypeSpace ) [ i] = tcx. types . err ;
2551
+ for & i in & ty_params {
2552
+ new_substs. types . get_mut_slice ( TypeSpace ) [ i] = tcx. types . err ;
2553
+ }
2541
2554
for & ty in fields. init ( ) {
2542
2555
if ty:: type_is_error ( ty. subst ( tcx, & new_substs) ) {
2543
2556
return Err ( Unimplemented ) ;
2544
2557
}
2545
2558
}
2546
2559
2547
- // Extract T and U from Struct<T> and Struct<U>.
2548
- let inner_source = * substs_a . types . get ( TypeSpace , i ) ;
2549
- let inner_target = * substs_b . types . get ( TypeSpace , i ) ;
2560
+ // Extract Field<T> and Field<U> from Struct<T> and Struct<U>.
2561
+ let inner_source = field . subst ( tcx , substs_a ) ;
2562
+ let inner_target = field . subst ( tcx , substs_b ) ;
2550
2563
2551
- // Check that all the source structure with the unsized
2552
- // type parameter is a subtype of the target.
2553
- new_substs. types . get_mut_slice ( TypeSpace ) [ i] = inner_target;
2564
+ // Check that the source structure with the target's
2565
+ // type parameters is a subtype of the target.
2566
+ for & i in & ty_params {
2567
+ let param_b = * substs_b. types . get ( TypeSpace , i) ;
2568
+ new_substs. types . get_mut_slice ( TypeSpace ) [ i] = param_b;
2569
+ }
2554
2570
let new_struct = ty:: mk_struct ( tcx, def_id, tcx. mk_substs ( new_substs) ) ;
2555
2571
let origin = infer:: Misc ( obligation. cause . span ) ;
2556
2572
if self . infcx . sub_types ( false , origin, new_struct, target) . is_err ( ) {
2557
2573
return Err ( Unimplemented ) ;
2558
2574
}
2559
2575
2560
- // Construct the nested T : Unsize<U > predicate.
2576
+ // Construct the nested Field<T> : Unsize<Field<U> > predicate.
2561
2577
nested. push ( util:: predicate_for_trait_def ( tcx,
2562
2578
obligation. cause . clone ( ) ,
2563
2579
obligation. predicate . def_id ( ) ,
0 commit comments