@@ -76,41 +76,154 @@ fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind {
7676 }
7777}
7878
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+
79209fn create_generic_args < ' tcx > (
80210 tcx : TyCtxt < ' tcx > ,
81211 def_id : LocalDefId ,
82212 sig_id : DefId ,
83213) -> 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) ;
86215
87216 let caller_kind = fn_kind ( tcx, def_id. into ( ) ) ;
88217 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+
91219 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)
114227 }
115228 // FIXME(fn_delegation): Only `Self` param supported here.
116229 ( FnKind :: AssocTraitImpl , FnKind :: AssocTrait )
@@ -120,7 +233,11 @@ fn create_generic_args<'tcx>(
120233 let generic_self_ty = ty:: GenericArg :: from ( self_ty) ;
121234 tcx. mk_args_from_iter ( std:: iter:: once ( generic_self_ty) )
122235 }
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 ! ( ) ,
124241 }
125242}
126243
@@ -129,74 +246,62 @@ pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
129246 def_id : LocalDefId ,
130247 sig_id : DefId ,
131248) -> 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) ;
137250
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) ;
146253
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 ( ) ) ,
149259
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 ! ( ) ,
159271 }
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- } )
173272}
174273
175274pub ( crate ) fn inherit_predicates_for_delegation_item < ' tcx > (
176275 tcx : TyCtxt < ' tcx > ,
177276 def_id : LocalDefId ,
178277 sig_id : DefId ,
179278) -> 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+
180285 // FIXME(fn_delegation): Support generics on associated delegation items.
181286 // 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+ }
188292
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 ! ( ) ,
192304 }
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- } )
200305}
201306
202307fn check_constraints < ' tcx > (
0 commit comments