@@ -2162,7 +2162,7 @@ pub(super) fn check_type_bounds<'tcx>(
21622162    impl_ty :  ty:: AssocItem , 
21632163    impl_trait_ref :  ty:: TraitRef < ' tcx > , 
21642164)  -> Result < ( ) ,  ErrorGuaranteed >  { 
2165-     let  param_env = param_env_with_gat_bounds ( tcx,  trait_ty ,   impl_ty,  impl_trait_ref) ; 
2165+     let  param_env = param_env_with_gat_bounds ( tcx,  impl_ty,  impl_trait_ref) ; 
21662166    debug ! ( ?param_env) ; 
21672167
21682168    let  container_id = impl_ty. container_id ( tcx) ; 
@@ -2239,7 +2239,13 @@ pub(super) fn check_type_bounds<'tcx>(
22392239    ocx. resolve_regions_and_report_errors ( impl_ty_def_id,  & outlives_env) 
22402240} 
22412241
2242- /// Given 
2242+ /// Install projection predicates that allow GATs to project to their own 
2243+ /// definition types. This is not allowed in general in cases of default 
2244+ /// associated types in trait definitions, or when specialization is involved, 
2245+ /// but is needed when checking these definition types actually satisfy the 
2246+ /// trait bounds of the GAT. 
2247+ /// 
2248+ /// # How it works 
22432249/// 
22442250/// impl<A, B> Foo<u32> for (A, B) { 
22452251///     type Bar<C> = Wrapper<A, B, C> 
@@ -2266,10 +2272,12 @@ pub(super) fn check_type_bounds<'tcx>(
22662272/// ```notrust 
22672273/// forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) } 
22682274/// ``` 
2275+ /// 
22692276/// when we really would like to generate 
22702277/// ```notrust 
22712278/// forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) :- Implemented(C: Eq) } 
22722279/// ``` 
2280+ /// 
22732281/// But, this is probably fine, because although the first clause can be used with types C that 
22742282/// do not implement Eq, for it to cause some kind of problem, there would have to be a 
22752283/// VecFamily::Member<X> for some type X where !(X: Eq), that appears in the value of type 
@@ -2278,92 +2286,118 @@ pub(super) fn check_type_bounds<'tcx>(
22782286/// the trait (notably, that X: Eq and T: Family). 
22792287fn  param_env_with_gat_bounds < ' tcx > ( 
22802288    tcx :  TyCtxt < ' tcx > , 
2281-     trait_ty :  ty:: AssocItem , 
22822289    impl_ty :  ty:: AssocItem , 
22832290    impl_trait_ref :  ty:: TraitRef < ' tcx > , 
22842291)  -> ty:: ParamEnv < ' tcx >  { 
22852292    let  param_env = tcx. param_env ( impl_ty. def_id ) ; 
22862293    let  container_id = impl_ty. container_id ( tcx) ; 
22872294    let  mut  predicates = param_env. caller_bounds ( ) . to_vec ( ) ; 
22882295
2289-     let  mut  bound_vars:  smallvec:: SmallVec < [ ty:: BoundVariableKind ;  8 ] >  =
2290-         smallvec:: SmallVec :: with_capacity ( tcx. generics_of ( impl_ty. def_id ) . params . len ( ) ) ; 
2291-     // Extend the impl's identity args with late-bound GAT vars 
2292-     let  normalize_impl_ty_args = ty:: GenericArgs :: identity_for_item ( tcx,  container_id) . extend_to ( 
2293-         tcx, 
2294-         impl_ty. def_id , 
2295-         |param,  _| match  param. kind  { 
2296-             GenericParamDefKind :: Type  {  .. }  => { 
2297-                 let  kind = ty:: BoundTyKind :: Param ( param. def_id ,  param. name ) ; 
2298-                 let  bound_var = ty:: BoundVariableKind :: Ty ( kind) ; 
2299-                 bound_vars. push ( bound_var) ; 
2300-                 Ty :: new_bound ( 
2301-                     tcx, 
2302-                     ty:: INNERMOST , 
2303-                     ty:: BoundTy  {  var :  ty:: BoundVar :: from_usize ( bound_vars. len ( )  - 1 ) ,  kind } , 
2304-                 ) 
2305-                 . into ( ) 
2296+     // for RPITITs, we should install predicates that allow us to project all 
2297+     // of the RPITITs associated with the same body. This is because checking 
2298+     // the item bounds of RPITITs often involves nested RPITITs having to prove 
2299+     // bounds about themselves. 
2300+     let  impl_tys_to_install = match  impl_ty. opt_rpitit_info  { 
2301+         None  => vec ! [ impl_ty] , 
2302+         Some ( 
2303+             ty:: ImplTraitInTraitData :: Impl  {  fn_def_id } 
2304+             | ty:: ImplTraitInTraitData :: Trait  {  fn_def_id,  .. } , 
2305+         )  => tcx
2306+             . associated_types_for_impl_traits_in_associated_fn ( fn_def_id) 
2307+             . iter ( ) 
2308+             . map ( |def_id| tcx. associated_item ( * def_id) ) 
2309+             . collect ( ) , 
2310+     } ; 
2311+ 
2312+     for  impl_ty in  impl_tys_to_install { 
2313+         let  trait_ty = match  impl_ty. container  { 
2314+             ty:: AssocItemContainer :: TraitContainer  => impl_ty, 
2315+             ty:: AssocItemContainer :: ImplContainer  => { 
2316+                 tcx. associated_item ( impl_ty. trait_item_def_id . unwrap ( ) ) 
23062317            } 
2307-             GenericParamDefKind :: Lifetime  => { 
2308-                 let  kind = ty:: BoundRegionKind :: BrNamed ( param. def_id ,  param. name ) ; 
2309-                 let  bound_var = ty:: BoundVariableKind :: Region ( kind) ; 
2310-                 bound_vars. push ( bound_var) ; 
2311-                 ty:: Region :: new_late_bound ( 
2312-                     tcx, 
2313-                     ty:: INNERMOST , 
2314-                     ty:: BoundRegion  {  var :  ty:: BoundVar :: from_usize ( bound_vars. len ( )  - 1 ) ,  kind } , 
2315-                 ) 
2316-                 . into ( ) 
2318+         } ; 
2319+ 
2320+         let  mut  bound_vars:  smallvec:: SmallVec < [ ty:: BoundVariableKind ;  8 ] >  =
2321+             smallvec:: SmallVec :: with_capacity ( tcx. generics_of ( impl_ty. def_id ) . params . len ( ) ) ; 
2322+         // Extend the impl's identity args with late-bound GAT vars 
2323+         let  normalize_impl_ty_args = ty:: GenericArgs :: identity_for_item ( tcx,  container_id) 
2324+             . extend_to ( tcx,  impl_ty. def_id ,  |param,  _| match  param. kind  { 
2325+                 GenericParamDefKind :: Type  {  .. }  => { 
2326+                     let  kind = ty:: BoundTyKind :: Param ( param. def_id ,  param. name ) ; 
2327+                     let  bound_var = ty:: BoundVariableKind :: Ty ( kind) ; 
2328+                     bound_vars. push ( bound_var) ; 
2329+                     Ty :: new_bound ( 
2330+                         tcx, 
2331+                         ty:: INNERMOST , 
2332+                         ty:: BoundTy  {  var :  ty:: BoundVar :: from_usize ( bound_vars. len ( )  - 1 ) ,  kind } , 
2333+                     ) 
2334+                     . into ( ) 
2335+                 } 
2336+                 GenericParamDefKind :: Lifetime  => { 
2337+                     let  kind = ty:: BoundRegionKind :: BrNamed ( param. def_id ,  param. name ) ; 
2338+                     let  bound_var = ty:: BoundVariableKind :: Region ( kind) ; 
2339+                     bound_vars. push ( bound_var) ; 
2340+                     ty:: Region :: new_late_bound ( 
2341+                         tcx, 
2342+                         ty:: INNERMOST , 
2343+                         ty:: BoundRegion  { 
2344+                             var :  ty:: BoundVar :: from_usize ( bound_vars. len ( )  - 1 ) , 
2345+                             kind, 
2346+                         } , 
2347+                     ) 
2348+                     . into ( ) 
2349+                 } 
2350+                 GenericParamDefKind :: Const  {  .. }  => { 
2351+                     let  bound_var = ty:: BoundVariableKind :: Const ; 
2352+                     bound_vars. push ( bound_var) ; 
2353+                     ty:: Const :: new_bound ( 
2354+                         tcx, 
2355+                         ty:: INNERMOST , 
2356+                         ty:: BoundVar :: from_usize ( bound_vars. len ( )  - 1 ) , 
2357+                         tcx. type_of ( param. def_id ) 
2358+                             . no_bound_vars ( ) 
2359+                             . expect ( "const parameter types cannot be generic" ) , 
2360+                     ) 
2361+                     . into ( ) 
2362+                 } 
2363+             } ) ; 
2364+         // When checking something like 
2365+         // 
2366+         // trait X { type Y: PartialEq<<Self as X>::Y> } 
2367+         // impl X for T { default type Y = S; } 
2368+         // 
2369+         // We will have to prove the bound S: PartialEq<<T as X>::Y>. In this case 
2370+         // we want <T as X>::Y to normalize to S. This is valid because we are 
2371+         // checking the default value specifically here. Add this equality to the 
2372+         // ParamEnv for normalization specifically. 
2373+         let  normalize_impl_ty =
2374+             tcx. type_of ( impl_ty. def_id ) . instantiate ( tcx,  normalize_impl_ty_args) ; 
2375+         let  rebased_args =
2376+             normalize_impl_ty_args. rebase_onto ( tcx,  container_id,  impl_trait_ref. args ) ; 
2377+         let  bound_vars = tcx. mk_bound_variable_kinds ( & bound_vars) ; 
2378+ 
2379+         match  normalize_impl_ty. kind ( )  { 
2380+             ty:: Alias ( ty:: Projection ,  proj) 
2381+                 if  proj. def_id  == trait_ty. def_id  && proj. args  == rebased_args =>
2382+             { 
2383+                 // Don't include this predicate if the projected type is 
2384+                 // exactly the same as the projection. This can occur in 
2385+                 // (somewhat dubious) code like this: 
2386+                 // 
2387+                 // impl<T> X for T where T: X { type Y = <T as X>::Y; } 
23172388            } 
2318-             GenericParamDefKind :: Const  {  .. }  => { 
2319-                 let  bound_var = ty:: BoundVariableKind :: Const ; 
2320-                 bound_vars. push ( bound_var) ; 
2321-                 ty:: Const :: new_bound ( 
2322-                     tcx, 
2323-                     ty:: INNERMOST , 
2324-                     ty:: BoundVar :: from_usize ( bound_vars. len ( )  - 1 ) , 
2325-                     tcx. type_of ( param. def_id ) 
2326-                         . no_bound_vars ( ) 
2327-                         . expect ( "const parameter types cannot be generic" ) , 
2389+             _ => predicates. push ( 
2390+                 ty:: Binder :: bind_with_vars ( 
2391+                     ty:: ProjectionPredicate  { 
2392+                         projection_ty :  ty:: AliasTy :: new ( tcx,  trait_ty. def_id ,  rebased_args) , 
2393+                         term :  normalize_impl_ty. into ( ) , 
2394+                     } , 
2395+                     bound_vars, 
23282396                ) 
2329-                 . into ( ) 
2330-             } 
2331-         } , 
2332-     ) ; 
2333-     // When checking something like 
2334-     // 
2335-     // trait X { type Y: PartialEq<<Self as X>::Y> } 
2336-     // impl X for T { default type Y = S; } 
2337-     // 
2338-     // We will have to prove the bound S: PartialEq<<T as X>::Y>. In this case 
2339-     // we want <T as X>::Y to normalize to S. This is valid because we are 
2340-     // checking the default value specifically here. Add this equality to the 
2341-     // ParamEnv for normalization specifically. 
2342-     let  normalize_impl_ty = tcx. type_of ( impl_ty. def_id ) . instantiate ( tcx,  normalize_impl_ty_args) ; 
2343-     let  rebased_args = normalize_impl_ty_args. rebase_onto ( tcx,  container_id,  impl_trait_ref. args ) ; 
2344-     let  bound_vars = tcx. mk_bound_variable_kinds ( & bound_vars) ; 
2345- 
2346-     match  normalize_impl_ty. kind ( )  { 
2347-         ty:: Alias ( ty:: Projection ,  proj) 
2348-             if  proj. def_id  == trait_ty. def_id  && proj. args  == rebased_args =>
2349-         { 
2350-             // Don't include this predicate if the projected type is 
2351-             // exactly the same as the projection. This can occur in 
2352-             // (somewhat dubious) code like this: 
2353-             // 
2354-             // impl<T> X for T where T: X { type Y = <T as X>::Y; } 
2355-         } 
2356-         _ => predicates. push ( 
2357-             ty:: Binder :: bind_with_vars ( 
2358-                 ty:: ProjectionPredicate  { 
2359-                     projection_ty :  ty:: AliasTy :: new ( tcx,  trait_ty. def_id ,  rebased_args) , 
2360-                     term :  normalize_impl_ty. into ( ) , 
2361-                 } , 
2362-                 bound_vars, 
2363-             ) 
2364-             . to_predicate ( tcx) , 
2365-         ) , 
2366-     } ; 
2397+                 . to_predicate ( tcx) , 
2398+             ) , 
2399+         } ; 
2400+     } 
23672401
23682402    ty:: ParamEnv :: new ( tcx. mk_clauses ( & predicates) ,  Reveal :: UserFacing ) 
23692403} 
0 commit comments