@@ -44,116 +44,129 @@ fn associated_type_bounds<'tcx>(
4444
4545 let item_trait_ref = ty:: TraitRef :: identity ( tcx, tcx. parent ( assoc_item_def_id. to_def_id ( ) ) ) ;
4646 let bounds_from_parent =
47- trait_predicates. predicates . iter ( ) . copied ( ) . filter_map ( |( pred, span) | {
48- let mut clause_ty = match pred. kind ( ) . skip_binder ( ) {
49- ty:: ClauseKind :: Trait ( tr) => tr. self_ty ( ) ,
50- ty:: ClauseKind :: Projection ( proj) => proj. projection_term . self_ty ( ) ,
51- ty:: ClauseKind :: TypeOutlives ( outlives) => outlives. 0 ,
52- _ => return None ,
53- } ;
47+ trait_predicates. predicates . iter ( ) . copied ( ) . filter_map ( |( clause, span) | {
48+ remap_gat_vars_and_recurse_into_nested_projections (
49+ tcx,
50+ filter,
51+ item_trait_ref,
52+ assoc_item_def_id,
53+ span,
54+ clause,
55+ )
56+ } ) ;
5457
55- // The code below is quite involved, so let me explain.
56- //
57- // We loop here, because we also want to collect vars for nested associated items as
58- // well. For example, given a clause like `Self::A::B`, we want to add that to the
59- // item bounds for `A`, so that we may use that bound in the case that `Self::A::B` is
60- // rigid.
61- //
62- // Secondly, regarding bound vars, when we see a where clause that mentions a GAT
63- // like `for<'a, ...> Self::Assoc<'a, ...>: Bound<'b, ...>`, we want to turn that into
64- // an item bound on the GAT, where all of the GAT args are substituted with the GAT's
65- // param regions, and then keep all of the other late-bound vars in the bound around.
66- // We need to "compress" the binder so that it doesn't mention any of those vars that
67- // were mapped to params.
68- let gat_vars = loop {
69- if let ty:: Alias ( ty:: Projection , alias_ty) = * clause_ty. kind ( ) {
70- if alias_ty. trait_ref ( tcx) == item_trait_ref
71- && alias_ty. def_id == assoc_item_def_id. to_def_id ( )
72- {
73- break & alias_ty. args [ item_trait_ref. args . len ( ) ..] ;
74- } else {
75- // Only collect *self* type bounds if the filter is for self.
76- match filter {
77- PredicateFilter :: SelfOnly | PredicateFilter :: SelfThatDefines ( _) => {
78- return None ;
79- }
80- PredicateFilter :: All | PredicateFilter :: SelfAndAssociatedTypeBounds => {
81- }
82- }
83-
84- clause_ty = alias_ty. self_ty ( ) ;
85- continue ;
58+ let all_bounds = tcx. arena . alloc_from_iter ( bounds. clauses ( tcx) . chain ( bounds_from_parent) ) ;
59+ debug ! (
60+ "associated_type_bounds({}) = {:?}" ,
61+ tcx. def_path_str( assoc_item_def_id. to_def_id( ) ) ,
62+ all_bounds
63+ ) ;
64+ all_bounds
65+ }
66+
67+ /// The code below is quite involved, so let me explain.
68+ ///
69+ /// We loop here, because we also want to collect vars for nested associated items as
70+ /// well. For example, given a clause like `Self::A::B`, we want to add that to the
71+ /// item bounds for `A`, so that we may use that bound in the case that `Self::A::B` is
72+ /// rigid.
73+ ///
74+ /// Secondly, regarding bound vars, when we see a where clause that mentions a GAT
75+ /// like `for<'a, ...> Self::Assoc<'a, ...>: Bound<'b, ...>`, we want to turn that into
76+ /// an item bound on the GAT, where all of the GAT args are substituted with the GAT's
77+ /// param regions, and then keep all of the other late-bound vars in the bound around.
78+ /// We need to "compress" the binder so that it doesn't mention any of those vars that
79+ /// were mapped to params.
80+ fn remap_gat_vars_and_recurse_into_nested_projections < ' tcx > (
81+ tcx : TyCtxt < ' tcx > ,
82+ filter : PredicateFilter ,
83+ item_trait_ref : ty:: TraitRef < ' tcx > ,
84+ assoc_item_def_id : LocalDefId ,
85+ span : Span ,
86+ clause : ty:: Clause < ' tcx > ,
87+ ) -> Option < ( ty:: Clause < ' tcx > , Span ) > {
88+ let mut clause_ty = match clause. kind ( ) . skip_binder ( ) {
89+ ty:: ClauseKind :: Trait ( tr) => tr. self_ty ( ) ,
90+ ty:: ClauseKind :: Projection ( proj) => proj. projection_term . self_ty ( ) ,
91+ ty:: ClauseKind :: TypeOutlives ( outlives) => outlives. 0 ,
92+ _ => return None ,
93+ } ;
94+
95+ let gat_vars = loop {
96+ if let ty:: Alias ( ty:: Projection , alias_ty) = * clause_ty. kind ( ) {
97+ if alias_ty. trait_ref ( tcx) == item_trait_ref
98+ && alias_ty. def_id == assoc_item_def_id. to_def_id ( )
99+ {
100+ // We have found the GAT in question...
101+ // Return the vars, since we may need to remap them.
102+ break & alias_ty. args [ item_trait_ref. args . len ( ) ..] ;
103+ } else {
104+ // Only collect *self* type bounds if the filter is for self.
105+ match filter {
106+ PredicateFilter :: SelfOnly | PredicateFilter :: SelfThatDefines ( _) => {
107+ return None ;
86108 }
109+ PredicateFilter :: All | PredicateFilter :: SelfAndAssociatedTypeBounds => { }
87110 }
88111
89- return None ;
90- } ;
91- // Special-case: No GAT vars, no mapping needed.
92- if gat_vars. is_empty ( ) {
93- return Some ( ( pred, span) ) ;
112+ clause_ty = alias_ty. self_ty ( ) ;
113+ continue ;
94114 }
115+ }
95116
96- // First, check that all of the GAT args are substituted with a unique late-bound arg.
97- // If we find a duplicate, then it can't be mapped to the definition's params.
98- let mut mapping = FxIndexMap :: default ( ) ;
99- let generics = tcx. generics_of ( assoc_item_def_id) ;
100- for ( param, var) in std:: iter:: zip ( & generics. own_params , gat_vars) {
101- let existing = match var. unpack ( ) {
102- ty:: GenericArgKind :: Lifetime ( re) => {
103- if let ty:: RegionKind :: ReBound ( ty:: INNERMOST , bv) = re. kind ( ) {
104- mapping. insert ( bv. var , tcx. mk_param_from_def ( param) )
105- } else {
106- return None ;
107- }
108- }
109- ty:: GenericArgKind :: Type ( ty) => {
110- if let ty:: Bound ( ty:: INNERMOST , bv) = * ty. kind ( ) {
111- mapping. insert ( bv. var , tcx. mk_param_from_def ( param) )
112- } else {
113- return None ;
114- }
115- }
116- ty:: GenericArgKind :: Const ( ct) => {
117- if let ty:: ConstKind :: Bound ( ty:: INNERMOST , bv) = ct. kind ( ) {
118- mapping. insert ( bv, tcx. mk_param_from_def ( param) )
119- } else {
120- return None ;
121- }
122- }
123- } ;
117+ return None ;
118+ } ;
124119
125- if existing. is_some ( ) {
120+ // Special-case: No GAT vars, no mapping needed.
121+ if gat_vars. is_empty ( ) {
122+ return Some ( ( clause, span) ) ;
123+ }
124+
125+ // First, check that all of the GAT args are substituted with a unique late-bound arg.
126+ // If we find a duplicate, then it can't be mapped to the definition's params.
127+ let mut mapping = FxIndexMap :: default ( ) ;
128+ let generics = tcx. generics_of ( assoc_item_def_id) ;
129+ for ( param, var) in std:: iter:: zip ( & generics. own_params , gat_vars) {
130+ let existing = match var. unpack ( ) {
131+ ty:: GenericArgKind :: Lifetime ( re) => {
132+ if let ty:: RegionKind :: ReBound ( ty:: INNERMOST , bv) = re. kind ( ) {
133+ mapping. insert ( bv. var , tcx. mk_param_from_def ( param) )
134+ } else {
126135 return None ;
127136 }
128137 }
138+ ty:: GenericArgKind :: Type ( ty) => {
139+ if let ty:: Bound ( ty:: INNERMOST , bv) = * ty. kind ( ) {
140+ mapping. insert ( bv. var , tcx. mk_param_from_def ( param) )
141+ } else {
142+ return None ;
143+ }
144+ }
145+ ty:: GenericArgKind :: Const ( ct) => {
146+ if let ty:: ConstKind :: Bound ( ty:: INNERMOST , bv) = ct. kind ( ) {
147+ mapping. insert ( bv, tcx. mk_param_from_def ( param) )
148+ } else {
149+ return None ;
150+ }
151+ }
152+ } ;
129153
130- // Finally, map all of the args in the GAT to the params we expect, and compress
131- // the remaining late-bound vars so that they count up from var 0.
132- let mut folder = MapAndCompressBoundVars {
133- tcx,
134- binder : ty:: INNERMOST ,
135- still_bound_vars : vec ! [ ] ,
136- mapping,
137- } ;
138- let pred = pred. kind ( ) . skip_binder ( ) . fold_with ( & mut folder) ;
139-
140- Some ( (
141- ty:: Binder :: bind_with_vars (
142- pred,
143- tcx. mk_bound_variable_kinds ( & folder. still_bound_vars ) ,
144- )
145- . upcast ( tcx) ,
146- span,
147- ) )
148- } ) ;
154+ if existing. is_some ( ) {
155+ return None ;
156+ }
157+ }
149158
150- let all_bounds = tcx. arena . alloc_from_iter ( bounds. clauses ( tcx) . chain ( bounds_from_parent) ) ;
151- debug ! (
152- "associated_type_bounds({}) = {:?}" ,
153- tcx. def_path_str( assoc_item_def_id. to_def_id( ) ) ,
154- all_bounds
155- ) ;
156- all_bounds
159+ // Finally, map all of the args in the GAT to the params we expect, and compress
160+ // the remaining late-bound vars so that they count up from var 0.
161+ let mut folder =
162+ MapAndCompressBoundVars { tcx, binder : ty:: INNERMOST , still_bound_vars : vec ! [ ] , mapping } ;
163+ let pred = clause. kind ( ) . skip_binder ( ) . fold_with ( & mut folder) ;
164+
165+ Some ( (
166+ ty:: Binder :: bind_with_vars ( pred, tcx. mk_bound_variable_kinds ( & folder. still_bound_vars ) )
167+ . upcast ( tcx) ,
168+ span,
169+ ) )
157170}
158171
159172struct MapAndCompressBoundVars < ' tcx > {
0 commit comments