1+ use itertools:: Itertools ;
12use rustc_data_structures:: fx:: FxHashMap ;
23use rustc_hir:: def:: DefKind ;
34use rustc_hir:: def_id:: { DefId , LocalDefId } ;
45use rustc_middle:: ty:: fold:: { TypeFoldable , TypeFolder , TypeSuperFoldable } ;
56use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
67use rustc_span:: ErrorGuaranteed ;
8+ use rustc_type_ir:: visit:: TypeVisitableExt ;
79
810type RemapTable = FxHashMap < u32 , u32 > ;
911
@@ -18,21 +20,39 @@ impl<'tcx, 'a> TypeFolder<TyCtxt<'tcx>> for IndicesFolder<'tcx, 'a> {
1820 }
1921
2022 fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
21- if let ty:: Param ( param) = ty. kind ( ) {
22- return Ty :: new_param ( self . tcx , self . remap_table [ & param. index ] , param. name ) ;
23+ if !ty. has_param ( ) {
24+ return ty;
25+ }
26+
27+ if let ty:: Param ( param) = ty. kind ( )
28+ && let Some ( idx) = self . remap_table . get ( & param. index )
29+ {
30+ return Ty :: new_param ( self . tcx , * idx, param. name ) ;
2331 }
2432 ty. super_fold_with ( self )
2533 }
2634
2735 fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
28- if let ty:: ReEarlyParam ( param) = r. kind ( ) {
36+ if let ty:: ReEarlyParam ( param) = r. kind ( )
37+ && let Some ( idx) = self . remap_table . get ( & param. index )
38+ {
2939 return ty:: Region :: new_early_param (
3040 self . tcx ,
31- ty:: EarlyParamRegion { index : self . remap_table [ & param . index ] , name : param. name } ,
41+ ty:: EarlyParamRegion { index : * idx , name : param. name } ,
3242 ) ;
3343 }
3444 r
3545 }
46+
47+ fn fold_const ( & mut self , ct : ty:: Const < ' tcx > ) -> ty:: Const < ' tcx > {
48+ if let ty:: ConstKind :: Param ( param) = ct. kind ( )
49+ && let Some ( idx) = self . remap_table . get ( & param. index )
50+ {
51+ let param = ty:: ParamConst :: new ( * idx, param. name ) ;
52+ return ty:: Const :: new_param ( self . tcx , param, ct. ty ( ) ) ;
53+ }
54+ ct. super_fold_with ( self )
55+ }
3656}
3757
3858#[ derive( Clone , Copy , Debug , PartialEq ) ]
@@ -55,28 +75,76 @@ fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind {
5575 }
5676}
5777
58- // Lifetime parameters must be declared before type and const parameters.
59- // Therefore, When delegating from a free function to a associated function,
60- // generic parameters need to be reordered:
61- //
62- // trait Trait<'a, A> {
63- // fn foo<'b, B>(...) {...}
64- // }
65- //
66- // reuse Trait::foo;
67- // desugaring:
68- // fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
69- // Trait::foo(...)
70- // }
71- fn create_remap_table < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId , sig_id : DefId ) -> RemapTable {
78+ fn create_generic_args < ' tcx > (
79+ tcx : TyCtxt < ' tcx > ,
80+ def_id : LocalDefId ,
81+ sig_id : DefId ,
82+ ) -> ty:: GenericArgsRef < ' tcx > {
7283 let caller_generics = tcx. generics_of ( def_id) ;
7384 let callee_generics = tcx. generics_of ( sig_id) ;
74- let mut remap_table: RemapTable = FxHashMap :: default ( ) ;
75- for caller_param in & caller_generics. own_params {
76- let callee_index = callee_generics. param_def_id_to_index ( tcx, caller_param. def_id ) . unwrap ( ) ;
77- remap_table. insert ( callee_index, caller_param. index ) ;
85+
86+ let caller_kind = fn_kind ( tcx, def_id. into ( ) ) ;
87+ let callee_kind = fn_kind ( tcx, sig_id) ;
88+ // FIXME(fn_delegation): early bound generics are only supported for trait
89+ // implementations and free functions. Error was reported in `check_constraints`.
90+ match ( caller_kind, callee_kind) {
91+ ( FnKind :: Free , _) => {
92+ let args = ty:: GenericArgs :: identity_for_item ( tcx, sig_id) ;
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 = FxHashMap :: 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 = IndicesFolder { tcx, remap_table : & remap_table } ;
113+ args. fold_with ( & mut folder)
114+ }
115+ ( FnKind :: AssocTraitImpl , FnKind :: AssocTrait ) => {
116+ let parent = tcx. parent ( def_id. into ( ) ) ;
117+ let parent_args =
118+ tcx. impl_trait_header ( parent) . unwrap ( ) . trait_ref . instantiate_identity ( ) . args ;
119+
120+ let callee_generics = tcx. generics_of ( sig_id) ;
121+ let trait_args = ty:: GenericArgs :: identity_for_item ( tcx, sig_id) ;
122+ let method_args = trait_args. iter ( ) . skip ( callee_generics. parent_count ) . collect_vec ( ) ;
123+
124+ // For trait implementations only the method's own parameters are copied.
125+ // They need to be reindexed adjusted for impl parameters.
126+ let mut remap_table: RemapTable = FxHashMap :: default ( ) ;
127+ let parent_count = caller_generics. parent_count as u32 ;
128+ for ( idx, callee_own_param) in callee_generics. own_params . iter ( ) . enumerate ( ) {
129+ let callee_index = callee_own_param. index as u32 ;
130+ remap_table. insert ( callee_index, idx as u32 + parent_count) ;
131+ }
132+ let mut folder = IndicesFolder { tcx, remap_table : & remap_table } ;
133+ let method_args = method_args. fold_with ( & mut folder) ;
134+
135+ tcx. mk_args_from_iter ( parent_args. iter ( ) . chain ( method_args) )
136+ }
137+ // only `Self` param supported here
138+ ( FnKind :: AssocInherentImpl , FnKind :: AssocTrait ) => {
139+ let parent = tcx. parent ( def_id. into ( ) ) ;
140+ let self_ty = tcx. type_of ( parent) . instantiate_identity ( ) ;
141+ let generic_self_ty = ty:: GenericArg :: from ( self_ty) ;
142+ tcx. mk_args_from_iter ( std:: iter:: once ( generic_self_ty) )
143+ }
144+ // `sig_id` is taken from corresponding trait method
145+ ( FnKind :: AssocTraitImpl , _) => unreachable ! ( ) ,
146+ _ => ty:: GenericArgs :: identity_for_item ( tcx, sig_id) ,
78147 }
79- remap_table
80148}
81149
82150pub ( crate ) fn inherit_generics_for_delegation_item < ' tcx > (
@@ -87,8 +155,12 @@ pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
87155 let caller_kind = fn_kind ( tcx, def_id. into ( ) ) ;
88156 let callee_kind = fn_kind ( tcx, sig_id) ;
89157
90- // FIXME(fn_delegation): Support generics on associated delegation items.
91- // Error was reported in `check_delegation_constraints`.
158+ let param_def_id_to_index = |own_params : & Vec < ty:: GenericParamDef > | {
159+ own_params. iter ( ) . map ( |param| ( param. def_id , param. index ) ) . collect ( )
160+ } ;
161+
162+ // FIXME(fn_delegation): early bound generics are only supported for trait
163+ // implementations and free functions. Error was reported in `check_constraints`.
92164 match ( caller_kind, callee_kind) {
93165 ( FnKind :: Free , _) => {
94166 let mut own_params = vec ! [ ] ;
@@ -112,14 +184,33 @@ pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
112184 }
113185 }
114186
115- let param_def_id_to_index =
116- own_params. iter ( ) . map ( |param| ( param. def_id , param. index ) ) . collect ( ) ;
117-
118187 Some ( ty:: Generics {
119188 parent : None ,
120189 parent_count : 0 ,
190+ param_def_id_to_index : param_def_id_to_index ( & own_params) ,
191+ own_params,
192+ has_self : false ,
193+ has_late_bound_regions : callee_generics. has_late_bound_regions ,
194+ host_effect_index : None ,
195+ } )
196+ }
197+ ( FnKind :: AssocTraitImpl , FnKind :: AssocTrait ) => {
198+ let callee_generics = tcx. generics_of ( sig_id) ;
199+
200+ let parent = tcx. parent ( def_id. into ( ) ) ;
201+ let parent_generics = tcx. generics_of ( parent) ;
202+ let parent_count = parent_generics. count ( ) ;
203+
204+ let mut own_params = tcx. generics_of ( sig_id) . own_params . clone ( ) ;
205+ for ( idx, param) in own_params. iter_mut ( ) . enumerate ( ) {
206+ param. index = ( parent_count + idx) as u32 ;
207+ }
208+
209+ Some ( ty:: Generics {
210+ parent : Some ( parent) ,
211+ parent_count,
212+ param_def_id_to_index : param_def_id_to_index ( & own_params) ,
121213 own_params,
122- param_def_id_to_index,
123214 has_self : false ,
124215 has_late_bound_regions : callee_generics. has_late_bound_regions ,
125216 host_effect_index : None ,
@@ -134,41 +225,38 @@ pub(crate) fn inherit_predicates_for_delegation_item<'tcx>(
134225 def_id : LocalDefId ,
135226 sig_id : DefId ,
136227) -> Option < ty:: GenericPredicates < ' tcx > > {
228+ // FIXME(fn_delegation): early bound generics are only supported for trait
229+ // implementations and free functions. Error was reported in `check_constraints`.
137230 let caller_kind = fn_kind ( tcx, def_id. into ( ) ) ;
138- let callee_kind = fn_kind ( tcx, sig_id) ;
139-
140- // FIXME(fn_delegation): Support generics on associated delegation items.
141- // Error was reported in `check_delegation_constraints`.
142- match ( caller_kind, callee_kind) {
143- ( FnKind :: Free , _) => {
144- let mut predicates = vec ! [ ] ;
145- let callee_predicates = tcx. predicates_of ( sig_id) ;
146- if let Some ( parent_sig_id) = callee_predicates. parent {
147- let parent_sig_predicates = tcx. predicates_of ( parent_sig_id) ;
148- predicates. extend_from_slice ( parent_sig_predicates. predicates ) ;
149- }
150- predicates. extend_from_slice ( callee_predicates. predicates ) ;
231+ if caller_kind != FnKind :: Free && caller_kind != FnKind :: AssocTraitImpl {
232+ return None ;
233+ }
151234
152- let remap_table = create_remap_table ( tcx, def_id, sig_id) ;
153- let mut folder = IndicesFolder { tcx, remap_table : & remap_table } ;
154- let predicates = predicates. fold_with ( & mut folder) ;
235+ let callee_predicates = tcx. predicates_of ( sig_id) ;
236+ let args = create_generic_args ( tcx, def_id, sig_id) ;
155237
156- Some ( ty:: GenericPredicates {
157- parent : None ,
158- predicates : tcx. arena . alloc_from_iter ( predicates) ,
159- } )
160- }
161- _ => None ,
238+ let mut preds = vec ! [ ] ;
239+ if let Some ( parent_id) = callee_predicates. parent {
240+ preds. extend ( tcx. predicates_of ( parent_id) . instantiate_own ( tcx, args) ) ;
162241 }
242+ preds. extend ( callee_predicates. instantiate_own ( tcx, args) ) ;
243+
244+ let parent = match fn_kind ( tcx, def_id. to_def_id ( ) ) {
245+ FnKind :: Free => None ,
246+ _ => Some ( tcx. parent ( def_id. into ( ) ) ) ,
247+ } ;
248+
249+ Some ( ty:: GenericPredicates { parent, predicates : tcx. arena . alloc_from_iter ( preds) } )
163250}
164251
165252fn check_constraints < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId ) -> Result < ( ) , ErrorGuaranteed > {
166253 let mut ret = Ok ( ( ) ) ;
167254 let sig_id = tcx. hir ( ) . delegation_sig_id ( def_id) ;
255+ let span = tcx. def_span ( def_id) ;
168256
169257 let mut emit = |descr| {
170258 ret = Err ( tcx. dcx ( ) . emit_err ( crate :: errors:: UnsupportedDelegation {
171- span : tcx . def_span ( def_id ) ,
259+ span,
172260 descr,
173261 callee_span : tcx. def_span ( sig_id) ,
174262 } ) ) ;
@@ -177,20 +265,33 @@ fn check_constraints<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Result<(),
177265 if let Some ( local_sig_id) = sig_id. as_local ( )
178266 && tcx. hir ( ) . opt_delegation_sig_id ( local_sig_id) . is_some ( )
179267 {
180- emit ( "recursive delegation" ) ;
268+ emit ( "recursive delegation is not supported yet " ) ;
181269 }
182270
183271 let caller_kind = fn_kind ( tcx, def_id. into ( ) ) ;
184- if caller_kind != FnKind :: Free {
185- let sig_generics = tcx. generics_of ( sig_id) ;
186- let parent = tcx. parent ( def_id. into ( ) ) ;
187- let parent_generics = tcx. generics_of ( parent) ;
272+ let callee_kind = fn_kind ( tcx, sig_id) ;
273+
274+ match ( caller_kind, callee_kind) {
275+ ( FnKind :: Free , _) | ( FnKind :: AssocTraitImpl , FnKind :: AssocTrait ) => { }
276+ // `sig_id` is taken from corresponding trait method
277+ ( FnKind :: AssocTraitImpl , _) => {
278+ return Err ( tcx
279+ . dcx ( )
280+ . span_delayed_bug ( span, "unexpected callee path resolution in delegation item" ) ) ;
281+ }
282+ _ => {
283+ let sig_generics = tcx. generics_of ( sig_id) ;
284+ let parent = tcx. parent ( def_id. into ( ) ) ;
285+ let parent_generics = tcx. generics_of ( parent) ;
188286
189- let parent_is_trait = ( tcx . def_kind ( parent ) == DefKind :: Trait ) as usize ;
190- let sig_has_self = sig_generics . has_self as usize ;
287+ let sig_has_self = sig_generics . has_self as usize ;
288+ let parent_has_self = parent_generics . has_self as usize ;
191289
192- if sig_generics. count ( ) > sig_has_self || parent_generics. count ( ) > parent_is_trait {
193- emit ( "early bound generics are not supported for associated delegation items" ) ;
290+ if sig_generics. count ( ) > sig_has_self || parent_generics. count ( ) > parent_has_self {
291+ emit (
292+ "early bound generics are only supported for trait implementations and free functions" ,
293+ ) ;
294+ }
194295 }
195296 }
196297
@@ -208,32 +309,11 @@ pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
208309 let err_type = Ty :: new_error ( tcx, err) ;
209310 return tcx. arena . alloc_from_iter ( ( 0 ..sig_len) . map ( |_| err_type) ) ;
210311 }
312+ let args = create_generic_args ( tcx, def_id, sig_id) ;
211313
212- let caller_kind = fn_kind ( tcx, def_id. into ( ) ) ;
213- let callee_kind = fn_kind ( tcx, sig_id) ;
214-
215- // FIXME(fn_delegation): Support generics on associated delegation items.
216- // Error was reported in `check_constraints`.
217- let sig = match ( caller_kind, callee_kind) {
218- ( FnKind :: Free , _) => {
219- let remap_table = create_remap_table ( tcx, def_id, sig_id) ;
220- let mut folder = IndicesFolder { tcx, remap_table : & remap_table } ;
221- caller_sig. instantiate_identity ( ) . fold_with ( & mut folder)
222- }
223- // only `Self` param supported here
224- ( FnKind :: AssocTraitImpl , FnKind :: AssocTrait )
225- | ( FnKind :: AssocInherentImpl , FnKind :: AssocTrait ) => {
226- let parent = tcx. parent ( def_id. into ( ) ) ;
227- let self_ty = tcx. type_of ( parent) . instantiate_identity ( ) ;
228- let generic_self_ty = ty:: GenericArg :: from ( self_ty) ;
229- let args = tcx. mk_args_from_iter ( std:: iter:: once ( generic_self_ty) ) ;
230- caller_sig. instantiate ( tcx, args)
231- }
232- _ => caller_sig. instantiate_identity ( ) ,
233- } ;
234314 // Bound vars are also inherited from `sig_id`.
235315 // They will be rebound later in `lower_fn_ty`.
236- let sig = sig . skip_binder ( ) ;
316+ let sig = caller_sig . instantiate ( tcx , args ) . skip_binder ( ) ;
237317 let sig_it = sig. inputs ( ) . iter ( ) . cloned ( ) . chain ( std:: iter:: once ( sig. output ( ) ) ) ;
238318 tcx. arena . alloc_from_iter ( sig_it)
239319}
0 commit comments