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