@@ -44,116 +44,129 @@ fn associated_type_bounds<'tcx>(
44
44
45
45
let item_trait_ref = ty:: TraitRef :: identity ( tcx, tcx. parent ( assoc_item_def_id. to_def_id ( ) ) ) ;
46
46
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
+ } ) ;
54
57
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 ;
86
108
}
109
+ PredicateFilter :: All | PredicateFilter :: SelfAndAssociatedTypeBounds => { }
87
110
}
88
111
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 ;
94
114
}
115
+ }
95
116
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
+ } ;
124
119
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 {
126
135
return None ;
127
136
}
128
137
}
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
+ } ;
129
153
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
+ }
149
158
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
+ ) )
157
170
}
158
171
159
172
struct MapAndCompressBoundVars < ' tcx > {
0 commit comments