@@ -76,41 +76,153 @@ 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
+ for ( idx, param) in own_params. iter_mut ( ) . enumerate ( ) {
119
+ param. index = idx as u32 ;
120
+ // FIXME(fn_delegation): Default parameters are not inherited, because they are
121
+ // not permitted in functions. Therefore, there are 2 options here:
122
+ //
123
+ // - We can create non-default generic parameters.
124
+ // - We can substitute default parameters into the signature.
125
+ //
126
+ // At the moment, first option has been selected as the most general.
127
+ if let ty:: GenericParamDefKind :: Type { has_default, .. }
128
+ | ty:: GenericParamDefKind :: Const { has_default, .. } = & mut param. kind
129
+ {
130
+ * has_default = false ;
131
+ }
132
+ }
133
+
134
+ ty:: Generics {
135
+ parent : self . parent ,
136
+ parent_count : 0 ,
137
+ own_params,
138
+ param_def_id_to_index,
139
+ has_self : false ,
140
+ has_late_bound_regions : sig_generics. has_late_bound_regions ,
141
+ host_effect_index : sig_generics. host_effect_index ,
142
+ }
143
+ }
144
+ }
145
+
146
+ struct PredicatesBuilder < ' tcx > {
147
+ tcx : TyCtxt < ' tcx > ,
148
+ args : ty:: GenericArgsRef < ' tcx > ,
149
+ parent : Option < DefId > ,
150
+ sig_id : DefId ,
151
+ }
152
+
153
+ impl < ' tcx > PredicatesBuilder < ' tcx > {
154
+ fn new (
155
+ tcx : TyCtxt < ' tcx > ,
156
+ args : ty:: GenericArgsRef < ' tcx > ,
157
+ sig_id : DefId ,
158
+ ) -> PredicatesBuilder < ' tcx > {
159
+ PredicatesBuilder { tcx, args, parent : None , sig_id }
160
+ }
161
+
162
+ fn build ( self ) -> ty:: GenericPredicates < ' tcx > {
163
+ let mut preds = vec ! [ ] ;
164
+
165
+ let sig_predicates = self . tcx . predicates_of ( self . sig_id ) ;
166
+ if let Some ( parent) = sig_predicates. parent {
167
+ let sig_parent_preds = self . tcx . predicates_of ( parent) ;
168
+ preds. extend ( sig_parent_preds. instantiate_own ( self . tcx , self . args ) ) ;
169
+ }
170
+ preds. extend ( sig_predicates. instantiate_own ( self . tcx , self . args ) ) ;
171
+
172
+ ty:: GenericPredicates {
173
+ parent : self . parent ,
174
+ predicates : self . tcx . arena . alloc_from_iter ( preds) ,
175
+ // FIXME(fn_delegation): Support effects.
176
+ effects_min_tys : ty:: List :: empty ( ) ,
177
+ }
178
+ }
179
+ }
180
+
181
+ struct GenericArgsBuilder < ' tcx > {
182
+ tcx : TyCtxt < ' tcx > ,
183
+ remap_table : RemapTable ,
184
+ sig_id : DefId ,
185
+ def_id : LocalDefId ,
186
+ }
187
+
188
+ impl < ' tcx > GenericArgsBuilder < ' tcx > {
189
+ fn new ( tcx : TyCtxt < ' tcx > , sig_id : DefId , def_id : LocalDefId ) -> GenericArgsBuilder < ' tcx > {
190
+ GenericArgsBuilder { tcx, remap_table : FxHashMap :: default ( ) , sig_id, def_id }
191
+ }
192
+
193
+ fn build_from_args ( mut self , args : ty:: GenericArgsRef < ' tcx > ) -> ty:: GenericArgsRef < ' tcx > {
194
+ let caller_generics = self . tcx . generics_of ( self . def_id ) ;
195
+ let callee_generics = self . tcx . generics_of ( self . sig_id ) ;
196
+
197
+ for caller_param in & caller_generics. own_params {
198
+ let callee_index =
199
+ callee_generics. param_def_id_to_index ( self . tcx , caller_param. def_id ) . unwrap ( ) ;
200
+ self . remap_table . insert ( callee_index, caller_param. index ) ;
201
+ }
202
+
203
+ let mut folder = ParamIndexRemapper { tcx : self . tcx , remap_table : self . remap_table } ;
204
+ args. fold_with ( & mut folder)
205
+ }
206
+ }
207
+
79
208
fn create_generic_args < ' tcx > (
80
209
tcx : TyCtxt < ' tcx > ,
81
210
def_id : LocalDefId ,
82
211
sig_id : DefId ,
83
212
) -> ty:: GenericArgsRef < ' tcx > {
84
- let caller_generics = tcx. generics_of ( def_id) ;
85
- let callee_generics = tcx. generics_of ( sig_id) ;
213
+ let builder = GenericArgsBuilder :: new ( tcx, sig_id, def_id) ;
86
214
87
215
let caller_kind = fn_kind ( tcx, def_id. into ( ) ) ;
88
216
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`.
217
+
91
218
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)
219
+ ( FnKind :: Free , FnKind :: Free )
220
+ | ( FnKind :: Free , FnKind :: AssocTrait )
221
+ | ( FnKind :: AssocInherentImpl , FnKind :: Free )
222
+ | ( FnKind :: AssocTrait , FnKind :: Free )
223
+ | ( FnKind :: AssocTrait , FnKind :: AssocTrait ) => {
224
+ let args = ty:: GenericArgs :: identity_for_item ( tcx, sig_id) ;
225
+ builder. build_from_args ( args)
114
226
}
115
227
// FIXME(fn_delegation): Only `Self` param supported here.
116
228
( FnKind :: AssocTraitImpl , FnKind :: AssocTrait )
@@ -120,7 +232,11 @@ fn create_generic_args<'tcx>(
120
232
let generic_self_ty = ty:: GenericArg :: from ( self_ty) ;
121
233
tcx. mk_args_from_iter ( std:: iter:: once ( generic_self_ty) )
122
234
}
123
- _ => ty:: GenericArgs :: identity_for_item ( tcx, sig_id) ,
235
+ // For trait impl's `sig_id` is always equal to the corresponding trait method.
236
+ ( FnKind :: AssocTraitImpl , _)
237
+ | ( _, FnKind :: AssocTraitImpl )
238
+ // Delegation to inherent methods is not yet supported.
239
+ | ( _, FnKind :: AssocInherentImpl ) => unreachable ! ( ) ,
124
240
}
125
241
}
126
242
@@ -129,74 +245,62 @@ pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
129
245
def_id : LocalDefId ,
130
246
sig_id : DefId ,
131
247
) -> 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
- }
248
+ let builder = GenericsBuilder :: new ( tcx, sig_id) ;
137
249
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 ( ) ) ;
250
+ let caller_kind = fn_kind ( tcx, def_id. into ( ) ) ;
251
+ let callee_kind = fn_kind ( tcx, sig_id) ;
146
252
147
- // Lifetimes go first.
148
- own_params. sort_by_key ( |key| key. kind . is_ty_or_const ( ) ) ;
253
+ // FIXME(fn_delegation): Support generics on associated delegation items.
254
+ // Error will be reported in `check_constraints`.
255
+ match ( caller_kind, callee_kind) {
256
+ ( FnKind :: Free , FnKind :: Free )
257
+ | ( FnKind :: Free , FnKind :: AssocTrait ) => Some ( builder. build ( ) ) ,
149
258
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
- }
259
+ ( FnKind :: AssocTraitImpl , FnKind :: AssocTrait )
260
+ | ( FnKind :: AssocInherentImpl , FnKind :: AssocTrait )
261
+ | ( FnKind :: AssocTrait , FnKind :: AssocTrait )
262
+ | ( FnKind :: AssocInherentImpl , FnKind :: Free )
263
+ | ( FnKind :: AssocTrait , FnKind :: Free ) => None ,
264
+
265
+ // For trait impl's `sig_id` is always equal to the corresponding trait method.
266
+ ( FnKind :: AssocTraitImpl , _)
267
+ | ( _, FnKind :: AssocTraitImpl )
268
+ // Delegation to inherent methods is not yet supported.
269
+ | ( _, FnKind :: AssocInherentImpl ) => unreachable ! ( ) ,
159
270
}
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
271
}
174
272
175
273
pub ( crate ) fn inherit_predicates_for_delegation_item < ' tcx > (
176
274
tcx : TyCtxt < ' tcx > ,
177
275
def_id : LocalDefId ,
178
276
sig_id : DefId ,
179
277
) -> Option < ty:: GenericPredicates < ' tcx > > {
278
+ let args = create_generic_args ( tcx, def_id, sig_id) ;
279
+ let builder = PredicatesBuilder :: new ( tcx, args, sig_id) ;
280
+
281
+ let caller_kind = fn_kind ( tcx, def_id. into ( ) ) ;
282
+ let callee_kind = fn_kind ( tcx, sig_id) ;
283
+
180
284
// FIXME(fn_delegation): Support generics on associated delegation items.
181
285
// 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) ;
286
+ match ( caller_kind, callee_kind) {
287
+ ( FnKind :: Free , FnKind :: Free )
288
+ | ( FnKind :: Free , FnKind :: AssocTrait ) => {
289
+ Some ( builder. build ( ) )
290
+ }
188
291
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) ) ;
292
+ ( FnKind :: AssocTraitImpl , FnKind :: AssocTrait )
293
+ | ( FnKind :: AssocInherentImpl , FnKind :: AssocTrait )
294
+ | ( FnKind :: AssocTrait , FnKind :: AssocTrait )
295
+ | ( FnKind :: AssocInherentImpl , FnKind :: Free )
296
+ | ( FnKind :: AssocTrait , FnKind :: Free ) => None ,
297
+
298
+ // For trait impl's `sig_id` is always equal to the corresponding trait method.
299
+ ( FnKind :: AssocTraitImpl , _)
300
+ | ( _, FnKind :: AssocTraitImpl )
301
+ // Delegation to inherent methods is not yet supported.
302
+ | ( _, FnKind :: AssocInherentImpl ) => unreachable ! ( ) ,
192
303
}
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
304
}
201
305
202
306
fn check_constraints < ' tcx > (
0 commit comments