@@ -76,41 +76,154 @@ fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind {
76
76
}
77
77
}
78
78
79
+ struct GenericsBuilder < ' tcx > {
80
+ tcx : TyCtxt < ' tcx > ,
81
+ sig_id : DefId ,
82
+ parent : Option < DefId > ,
83
+ }
84
+
85
+ impl < ' tcx > GenericsBuilder < ' tcx > {
86
+ fn new ( tcx : TyCtxt < ' tcx > , sig_id : DefId ) -> GenericsBuilder < ' tcx > {
87
+ GenericsBuilder { tcx, sig_id, parent : None }
88
+ }
89
+
90
+ fn build ( self ) -> ty:: Generics {
91
+ let mut own_params = vec ! [ ] ;
92
+
93
+ let sig_generics = self . tcx . generics_of ( self . sig_id ) ;
94
+ if let Some ( parent_def_id) = sig_generics. parent {
95
+ let sig_parent_generics = self . tcx . generics_of ( parent_def_id) ;
96
+ own_params. append ( & mut sig_parent_generics. own_params . clone ( ) ) ;
97
+ }
98
+ own_params. append ( & mut sig_generics. own_params . clone ( ) ) ;
99
+
100
+ // Lifetime parameters must be declared before type and const parameters.
101
+ // Therefore, When delegating from a free function to a associated function,
102
+ // generic parameters need to be reordered:
103
+ //
104
+ // trait Trait<'a, A> {
105
+ // fn foo<'b, B>(...) {...}
106
+ // }
107
+ //
108
+ // reuse Trait::foo;
109
+ // desugaring:
110
+ // fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
111
+ // Trait::foo(...)
112
+ // }
113
+ own_params. sort_by_key ( |key| key. kind . is_ty_or_const ( ) ) ;
114
+
115
+ let param_def_id_to_index =
116
+ own_params. iter ( ) . map ( |param| ( param. def_id , param. index ) ) . collect ( ) ;
117
+
118
+ let ( parent_count, has_self) = if let Some ( def_id) = self . parent {
119
+ let parent_generics = self . tcx . generics_of ( def_id) ;
120
+ let parent_kind = self . tcx . def_kind ( def_id) ;
121
+ ( parent_generics. count ( ) , parent_kind == DefKind :: Trait )
122
+ } else {
123
+ ( 0 , false )
124
+ } ;
125
+
126
+ for ( idx, param) in own_params. iter_mut ( ) . enumerate ( ) {
127
+ param. index = ( idx + parent_count) as u32 ;
128
+ // Default type parameters are not inherited: they are not allowed
129
+ // in fn's.
130
+ if let ty:: GenericParamDefKind :: Type { synthetic, .. } = param. kind {
131
+ param. kind = ty:: GenericParamDefKind :: Type { has_default : false , synthetic }
132
+ }
133
+ }
134
+
135
+ ty:: Generics {
136
+ parent : self . parent ,
137
+ parent_count,
138
+ own_params,
139
+ param_def_id_to_index,
140
+ has_self,
141
+ has_late_bound_regions : sig_generics. has_late_bound_regions ,
142
+ host_effect_index : sig_generics. host_effect_index ,
143
+ }
144
+ }
145
+ }
146
+
147
+ struct PredicatesBuilder < ' tcx > {
148
+ tcx : TyCtxt < ' tcx > ,
149
+ args : ty:: GenericArgsRef < ' tcx > ,
150
+ parent : Option < DefId > ,
151
+ sig_id : DefId ,
152
+ }
153
+
154
+ impl < ' tcx > PredicatesBuilder < ' tcx > {
155
+ fn new (
156
+ tcx : TyCtxt < ' tcx > ,
157
+ args : ty:: GenericArgsRef < ' tcx > ,
158
+ sig_id : DefId ,
159
+ ) -> PredicatesBuilder < ' tcx > {
160
+ PredicatesBuilder { tcx, args, parent : None , sig_id }
161
+ }
162
+
163
+ fn build ( self ) -> ty:: GenericPredicates < ' tcx > {
164
+ let mut preds = vec ! [ ] ;
165
+
166
+ let sig_predicates = self . tcx . predicates_of ( self . sig_id ) ;
167
+ if let Some ( parent) = sig_predicates. parent {
168
+ let sig_parent_preds = self . tcx . predicates_of ( parent) ;
169
+ preds. extend ( sig_parent_preds. instantiate_own ( self . tcx , self . args ) ) ;
170
+ }
171
+ preds. extend ( sig_predicates. instantiate_own ( self . tcx , self . args ) ) ;
172
+
173
+ ty:: GenericPredicates {
174
+ parent : self . parent ,
175
+ predicates : self . tcx . arena . alloc_from_iter ( preds) ,
176
+ // FIXME(fn_delegation): Support effects.
177
+ effects_min_tys : ty:: List :: empty ( ) ,
178
+ }
179
+ }
180
+ }
181
+
182
+ struct GenericArgsBuilder < ' tcx > {
183
+ tcx : TyCtxt < ' tcx > ,
184
+ remap_table : RemapTable ,
185
+ sig_id : DefId ,
186
+ def_id : LocalDefId ,
187
+ }
188
+
189
+ impl < ' tcx > GenericArgsBuilder < ' tcx > {
190
+ fn new ( tcx : TyCtxt < ' tcx > , sig_id : DefId , def_id : LocalDefId ) -> GenericArgsBuilder < ' tcx > {
191
+ GenericArgsBuilder { tcx, remap_table : FxHashMap :: default ( ) , sig_id, def_id }
192
+ }
193
+
194
+ fn build_from_args ( mut self , args : ty:: GenericArgsRef < ' tcx > ) -> ty:: GenericArgsRef < ' tcx > {
195
+ let caller_generics = self . tcx . generics_of ( self . def_id ) ;
196
+ let callee_generics = self . tcx . generics_of ( self . sig_id ) ;
197
+
198
+ for caller_param in & caller_generics. own_params {
199
+ let callee_index =
200
+ callee_generics. param_def_id_to_index ( self . tcx , caller_param. def_id ) . unwrap ( ) ;
201
+ self . remap_table . insert ( callee_index, caller_param. index ) ;
202
+ }
203
+
204
+ let mut folder = ParamIndexRemapper { tcx : self . tcx , remap_table : self . remap_table } ;
205
+ args. fold_with ( & mut folder)
206
+ }
207
+ }
208
+
79
209
fn create_generic_args < ' tcx > (
80
210
tcx : TyCtxt < ' tcx > ,
81
211
def_id : LocalDefId ,
82
212
sig_id : DefId ,
83
213
) -> ty:: GenericArgsRef < ' tcx > {
84
- let caller_generics = tcx. generics_of ( def_id) ;
85
- let callee_generics = tcx. generics_of ( sig_id) ;
214
+ let builder = GenericArgsBuilder :: new ( tcx, sig_id, def_id) ;
86
215
87
216
let caller_kind = fn_kind ( tcx, def_id. into ( ) ) ;
88
217
let callee_kind = fn_kind ( tcx, sig_id) ;
89
- // FIXME(fn_delegation): Support generics on associated delegation items.
90
- // Error will be reported in `check_constraints`.
218
+
91
219
match ( caller_kind, callee_kind) {
92
- ( FnKind :: Free , _) => {
93
- // Lifetime parameters must be declared before type and const parameters.
94
- // Therefore, When delegating from a free function to a associated function,
95
- // generic parameters need to be reordered:
96
- //
97
- // trait Trait<'a, A> {
98
- // fn foo<'b, B>(...) {...}
99
- // }
100
- //
101
- // reuse Trait::foo;
102
- // desugaring:
103
- // fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
104
- // Trait::foo(...)
105
- // }
106
- let mut remap_table = RemapTable :: default ( ) ;
107
- for caller_param in & caller_generics. own_params {
108
- let callee_index =
109
- callee_generics. param_def_id_to_index ( tcx, caller_param. def_id ) . unwrap ( ) ;
110
- remap_table. insert ( callee_index, caller_param. index ) ;
111
- }
112
- let mut folder = ParamIndexRemapper { tcx, remap_table } ;
113
- ty:: GenericArgs :: identity_for_item ( tcx, sig_id) . fold_with ( & mut folder)
220
+ ( FnKind :: Free , FnKind :: Free )
221
+ | ( FnKind :: Free , FnKind :: AssocTrait )
222
+ | ( FnKind :: AssocInherentImpl , FnKind :: Free )
223
+ | ( FnKind :: AssocTrait , FnKind :: Free )
224
+ | ( FnKind :: AssocTrait , FnKind :: AssocTrait ) => {
225
+ let args = ty:: GenericArgs :: identity_for_item ( tcx, sig_id) ;
226
+ builder. build_from_args ( args)
114
227
}
115
228
// FIXME(fn_delegation): Only `Self` param supported here.
116
229
( FnKind :: AssocTraitImpl , FnKind :: AssocTrait )
@@ -120,7 +233,11 @@ fn create_generic_args<'tcx>(
120
233
let generic_self_ty = ty:: GenericArg :: from ( self_ty) ;
121
234
tcx. mk_args_from_iter ( std:: iter:: once ( generic_self_ty) )
122
235
}
123
- _ => ty:: GenericArgs :: identity_for_item ( tcx, sig_id) ,
236
+ // For trait impl's `sig_id` is always equal to the corresponding trait method.
237
+ ( FnKind :: AssocTraitImpl , _)
238
+ | ( _, FnKind :: AssocTraitImpl )
239
+ // Delegation to inherent methods is not yet supported.
240
+ | ( _, FnKind :: AssocInherentImpl ) => unreachable ! ( ) ,
124
241
}
125
242
}
126
243
@@ -129,74 +246,62 @@ pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
129
246
def_id : LocalDefId ,
130
247
sig_id : DefId ,
131
248
) -> Option < ty:: Generics > {
132
- // FIXME(fn_delegation): Support generics on associated delegation items.
133
- // Error will be reported in `check_constraints`.
134
- if fn_kind ( tcx, def_id. into ( ) ) != FnKind :: Free {
135
- return None ;
136
- }
249
+ let builder = GenericsBuilder :: new ( tcx, sig_id) ;
137
250
138
- let mut own_params = vec ! [ ] ;
139
-
140
- let callee_generics = tcx. generics_of ( sig_id) ;
141
- if let Some ( parent_sig_id) = callee_generics. parent {
142
- let parent_sig_generics = tcx. generics_of ( parent_sig_id) ;
143
- own_params. append ( & mut parent_sig_generics. own_params . clone ( ) ) ;
144
- }
145
- own_params. append ( & mut callee_generics. own_params . clone ( ) ) ;
251
+ let caller_kind = fn_kind ( tcx, def_id. into ( ) ) ;
252
+ let callee_kind = fn_kind ( tcx, sig_id) ;
146
253
147
- // Lifetimes go first.
148
- own_params. sort_by_key ( |key| key. kind . is_ty_or_const ( ) ) ;
254
+ // FIXME(fn_delegation): Support generics on associated delegation items.
255
+ // Error will be reported in `check_constraints`.
256
+ match ( caller_kind, callee_kind) {
257
+ ( FnKind :: Free , FnKind :: Free )
258
+ | ( FnKind :: Free , FnKind :: AssocTrait ) => Some ( builder. build ( ) ) ,
149
259
150
- for ( idx, param) in own_params. iter_mut ( ) . enumerate ( ) {
151
- param. index = idx as u32 ;
152
- // Default parameters are not inherited: they are not allowed
153
- // in fn's.
154
- if let ty:: GenericParamDefKind :: Type { has_default, .. }
155
- | ty:: GenericParamDefKind :: Const { has_default, .. } = & mut param. kind
156
- {
157
- * has_default = false ;
158
- }
260
+ ( FnKind :: AssocTraitImpl , FnKind :: AssocTrait )
261
+ | ( FnKind :: AssocInherentImpl , FnKind :: AssocTrait )
262
+ | ( FnKind :: AssocTrait , FnKind :: AssocTrait )
263
+ | ( FnKind :: AssocInherentImpl , FnKind :: Free )
264
+ | ( FnKind :: AssocTrait , FnKind :: Free ) => None ,
265
+
266
+ // For trait impl's `sig_id` is always equal to the corresponding trait method.
267
+ ( FnKind :: AssocTraitImpl , _)
268
+ | ( _, FnKind :: AssocTraitImpl )
269
+ // Delegation to inherent methods is not yet supported.
270
+ | ( _, FnKind :: AssocInherentImpl ) => unreachable ! ( ) ,
159
271
}
160
-
161
- let param_def_id_to_index =
162
- own_params. iter ( ) . map ( |param| ( param. def_id , param. index ) ) . collect ( ) ;
163
-
164
- Some ( ty:: Generics {
165
- parent : None ,
166
- parent_count : 0 ,
167
- own_params,
168
- param_def_id_to_index,
169
- has_self : false ,
170
- has_late_bound_regions : callee_generics. has_late_bound_regions ,
171
- host_effect_index : callee_generics. host_effect_index ,
172
- } )
173
272
}
174
273
175
274
pub ( crate ) fn inherit_predicates_for_delegation_item < ' tcx > (
176
275
tcx : TyCtxt < ' tcx > ,
177
276
def_id : LocalDefId ,
178
277
sig_id : DefId ,
179
278
) -> Option < ty:: GenericPredicates < ' tcx > > {
279
+ let args = create_generic_args ( tcx, def_id, sig_id) ;
280
+ let builder = PredicatesBuilder :: new ( tcx, args, sig_id) ;
281
+
282
+ let caller_kind = fn_kind ( tcx, def_id. into ( ) ) ;
283
+ let callee_kind = fn_kind ( tcx, sig_id) ;
284
+
180
285
// FIXME(fn_delegation): Support generics on associated delegation items.
181
286
// Error will be reported in `check_constraints`.
182
- if fn_kind ( tcx, def_id. into ( ) ) != FnKind :: Free {
183
- return None ;
184
- }
185
-
186
- let callee_predicates = tcx. predicates_of ( sig_id) ;
187
- let args = create_generic_args ( tcx, def_id, sig_id) ;
287
+ match ( caller_kind, callee_kind) {
288
+ ( FnKind :: Free , FnKind :: Free )
289
+ | ( FnKind :: Free , FnKind :: AssocTrait ) => {
290
+ Some ( builder. build ( ) )
291
+ }
188
292
189
- let mut preds = vec ! [ ] ;
190
- if let Some ( parent_id) = callee_predicates. parent {
191
- preds. extend ( tcx. predicates_of ( parent_id) . instantiate_own ( tcx, args) ) ;
293
+ ( FnKind :: AssocTraitImpl , FnKind :: AssocTrait )
294
+ | ( FnKind :: AssocInherentImpl , FnKind :: AssocTrait )
295
+ | ( FnKind :: AssocTrait , FnKind :: AssocTrait )
296
+ | ( FnKind :: AssocInherentImpl , FnKind :: Free )
297
+ | ( FnKind :: AssocTrait , FnKind :: Free ) => None ,
298
+
299
+ // For trait impl's `sig_id` is always equal to the corresponding trait method.
300
+ ( FnKind :: AssocTraitImpl , _)
301
+ | ( _, FnKind :: AssocTraitImpl )
302
+ // Delegation to inherent methods is not yet supported.
303
+ | ( _, FnKind :: AssocInherentImpl ) => unreachable ! ( ) ,
192
304
}
193
- preds. extend ( callee_predicates. instantiate_own ( tcx, args) ) ;
194
-
195
- Some ( ty:: GenericPredicates {
196
- parent : None ,
197
- predicates : tcx. arena . alloc_from_iter ( preds) ,
198
- effects_min_tys : ty:: List :: empty ( ) ,
199
- } )
200
305
}
201
306
202
307
fn check_constraints < ' tcx > (
0 commit comments