@@ -45,107 +45,15 @@ fn associated_type_bounds<'tcx>(
45
45
46
46
let item_trait_ref = ty:: TraitRef :: identity ( tcx, tcx. parent ( assoc_item_def_id. to_def_id ( ) ) ) ;
47
47
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 (
134
50
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,
147
54
span,
148
- ) )
55
+ clause,
56
+ )
149
57
} ) ;
150
58
151
59
let all_bounds = tcx. arena . alloc_from_iter ( bounds. clauses ( tcx) . chain ( bounds_from_parent) ) ;
@@ -160,6 +68,111 @@ fn associated_type_bounds<'tcx>(
160
68
all_bounds
161
69
}
162
70
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
+
163
176
struct MapAndCompressBoundVars < ' tcx > {
164
177
tcx : TyCtxt < ' tcx > ,
165
178
/// How deep are we? Makes sure we don't touch the vars of nested binders.
0 commit comments