@@ -2523,41 +2523,57 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
25232523 ty:: lookup_field_type_unsubstituted ( tcx, def_id, f. id )
25242524 } ) . collect :: < Vec < _ > > ( ) ;
25252525
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
25312529 } else {
25322530 return Err ( Unimplemented ) ;
25332531 } ;
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+ }
25342545
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.
25372548 // This could be checked after type collection for any struct
25382549 // with a potentially unsized trailing field.
25392550 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+ }
25412554 for & ty in fields. init ( ) {
25422555 if ty:: type_is_error ( ty. subst ( tcx, & new_substs) ) {
25432556 return Err ( Unimplemented ) ;
25442557 }
25452558 }
25462559
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 ) ;
25502563
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+ }
25542570 let new_struct = ty:: mk_struct ( tcx, def_id, tcx. mk_substs ( new_substs) ) ;
25552571 let origin = infer:: Misc ( obligation. cause . span ) ;
25562572 if self . infcx . sub_types ( false , origin, new_struct, target) . is_err ( ) {
25572573 return Err ( Unimplemented ) ;
25582574 }
25592575
2560- // Construct the nested T : Unsize<U > predicate.
2576+ // Construct the nested Field<T> : Unsize<Field<U> > predicate.
25612577 nested. push ( util:: predicate_for_trait_def ( tcx,
25622578 obligation. cause . clone ( ) ,
25632579 obligation. predicate . def_id ( ) ,
0 commit comments