@@ -20,6 +20,10 @@ pub(super) enum DelegationGenerics<T> {
2020 /// In free-to-trait reuse, when user specified args for trait `reuse Trait::<i32>::foo;`
2121 /// in this case we need to both generate `Self` and process user args.
2222 SelfAndUserSpecified ( Option < T > ) ,
23+ /// In delegations from trait impl to other entities like free functions or trait functions,
24+ /// we want to generate a function whose generics matches generics of signature function
25+ /// in trait.
26+ TraitImpl ( Option < T > , bool /* Has user-specified args */ ) ,
2327}
2428
2529/// Used for storing either AST generics or their lowered HIR version. Firstly we obtain
@@ -38,28 +42,39 @@ pub(super) enum HirOrAstGenerics<'hir> {
3842 Hir ( DelegationGenerics < & ' hir hir:: Generics < ' hir > > ) ,
3943}
4044
41- pub ( super ) enum PropagationKind {
42- Allowed ,
43- Forbidden ,
44- }
45-
4645pub ( super ) struct GenericsGenerationResult < ' hir > {
4746 pub ( super ) generics : HirOrAstGenerics < ' hir > ,
4847 pub ( super ) args_segment_id : Option < HirId > ,
49- pub ( super ) propagation_kind : PropagationKind ,
5048}
5149
5250pub ( super ) struct GenericsGenerationResults < ' hir > {
5351 pub ( super ) parent : GenericsGenerationResult < ' hir > ,
5452 pub ( super ) child : GenericsGenerationResult < ' hir > ,
5553}
5654
55+ pub ( super ) struct GenericArgsPropagationDetails {
56+ pub ( super ) should_propagate : bool ,
57+ pub ( super ) use_args_in_sig_inheritance : bool ,
58+ }
59+
5760impl < T > DelegationGenerics < T > {
58- fn is_user_specified ( & self ) -> bool {
59- matches ! (
60- self ,
61- DelegationGenerics :: UserSpecified | DelegationGenerics :: SelfAndUserSpecified { .. }
62- )
61+ fn get_args_propagation_details ( & self ) -> GenericArgsPropagationDetails {
62+ match self {
63+ DelegationGenerics :: UserSpecified | DelegationGenerics :: SelfAndUserSpecified { .. } => {
64+ GenericArgsPropagationDetails {
65+ should_propagate : false ,
66+ use_args_in_sig_inheritance : true ,
67+ }
68+ }
69+ DelegationGenerics :: TraitImpl ( _, user_specified) => GenericArgsPropagationDetails {
70+ should_propagate : !* user_specified,
71+ use_args_in_sig_inheritance : false ,
72+ } ,
73+ DelegationGenerics :: Default ( _) => GenericArgsPropagationDetails {
74+ should_propagate : true ,
75+ use_args_in_sig_inheritance : false ,
76+ } ,
77+ }
6378 }
6479}
6580
@@ -83,6 +98,12 @@ impl<'hir> HirOrAstGenerics<'hir> {
8398 DelegationGenerics :: SelfAndUserSpecified ( generics) => {
8499 DelegationGenerics :: SelfAndUserSpecified ( generics. as_mut ( ) . map ( process_params) )
85100 }
101+ DelegationGenerics :: TraitImpl ( generics, user_specified) => {
102+ DelegationGenerics :: TraitImpl (
103+ generics. as_mut ( ) . map ( process_params) ,
104+ * user_specified,
105+ )
106+ }
86107 } ;
87108
88109 * self = HirOrAstGenerics :: Hir ( hir_generics) ;
@@ -97,7 +118,8 @@ impl<'hir> HirOrAstGenerics<'hir> {
97118 HirOrAstGenerics :: Hir ( hir_generics) => match hir_generics {
98119 DelegationGenerics :: UserSpecified => hir:: Generics :: empty ( ) ,
99120 DelegationGenerics :: Default ( generics)
100- | DelegationGenerics :: SelfAndUserSpecified ( generics) => {
121+ | DelegationGenerics :: SelfAndUserSpecified ( generics)
122+ | DelegationGenerics :: TraitImpl ( generics, _) => {
101123 generics. unwrap_or ( hir:: Generics :: empty ( ) )
102124 }
103125 } ,
@@ -117,36 +139,29 @@ impl<'hir> HirOrAstGenerics<'hir> {
117139 HirOrAstGenerics :: Hir ( hir_generics) => match hir_generics {
118140 DelegationGenerics :: UserSpecified => None ,
119141 DelegationGenerics :: Default ( generics)
120- | DelegationGenerics :: SelfAndUserSpecified ( generics) => generics. map ( |generics| {
142+ | DelegationGenerics :: SelfAndUserSpecified ( generics)
143+ | DelegationGenerics :: TraitImpl ( generics, _) => generics. map ( |generics| {
121144 ctx. create_generics_args_from_params ( generics. params , add_lifetimes, span)
122145 } ) ,
123146 } ,
124147 }
125148 }
126149
127- pub ( super ) fn is_user_specified ( & self ) -> bool {
150+ pub ( super ) fn get_args_propagation_details ( & self ) -> GenericArgsPropagationDetails {
128151 match self {
129- HirOrAstGenerics :: Ast ( ast_generics) => ast_generics. is_user_specified ( ) ,
130- HirOrAstGenerics :: Hir ( hir_generics) => hir_generics. is_user_specified ( ) ,
152+ HirOrAstGenerics :: Ast ( ast_generics) => ast_generics. get_args_propagation_details ( ) ,
153+ HirOrAstGenerics :: Hir ( hir_generics) => hir_generics. get_args_propagation_details ( ) ,
131154 }
132155 }
133156}
134157
135158impl < ' a > GenericsGenerationResult < ' a > {
136- fn new (
137- generics : DelegationGenerics < Generics > ,
138- propagation_kind : PropagationKind ,
139- ) -> GenericsGenerationResult < ' a > {
159+ fn new ( generics : DelegationGenerics < Generics > ) -> GenericsGenerationResult < ' a > {
140160 GenericsGenerationResult {
141161 generics : HirOrAstGenerics :: Ast ( generics) ,
142162 args_segment_id : None ,
143- propagation_kind,
144163 }
145164 }
146-
147- pub ( super ) fn can_propagate ( & self ) -> bool {
148- matches ! ( self . propagation_kind, PropagationKind :: Allowed )
149- }
150165}
151166
152167impl < ' hir > GenericsGenerationResults < ' hir > {
@@ -161,8 +176,6 @@ impl<'hir> GenericsGenerationResults<'hir> {
161176 // method call will be supported (if HIR generics were not obtained
162177 // then it means that we did not propagated them, thus we do not need
163178 // to generate params).
164- // FIXME(fn_delegation): in impl trait case we still need to generate
165- // generic params, so this should be reworked.
166179 let parent = self
167180 . parent
168181 . generics
@@ -205,8 +218,6 @@ impl<'hir> GenericsGenerationResults<'hir> {
205218 // method call will be supported (if HIR generics were not obtained
206219 // then it means that we did not propagated them, thus we do not need
207220 // to generate predicates).
208- // FIXME(fn_delegation): in impl trait case we still need to generate
209- // generic params, so this should be reworked.
210221 self . parent
211222 . generics
212223 . into_hir_generics ( ctx, item_id, span)
@@ -236,29 +247,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
236247 let delegation_parent_kind =
237248 self . tcx . def_kind ( self . tcx . local_parent ( self . local_def_id ( item_id) ) ) ;
238249
250+ let segments = & delegation. path . segments ;
251+ let len = segments. len ( ) ;
252+ let child_user_specified = segments[ len - 1 ] . args . is_some ( ) ;
253+
239254 // If we are in impl trait always generate function whose generics matches
240255 // those that are defined in trait.
241256 if matches ! ( delegation_parent_kind, DefKind :: Impl { of_trait: true } ) {
242257 // Considering parent generics, during signature inheritance
243258 // we will take those args that are in impl trait header trait ref.
244- let parent = GenericsGenerationResult :: new (
245- DelegationGenerics :: Default ( None ) ,
246- PropagationKind :: Forbidden ,
247- ) ;
259+ let parent = GenericsGenerationResult :: new ( DelegationGenerics :: Default ( None ) ) ;
248260
249- // Check if we can propagate generics: now we do it only if delegation
250- // path resolution matches the signature.
251- // FIXME(fn_delegation): more advanced checks for propagation,
252- // i.e., comparing generics of signature and `res` fn.
253- let res = self . get_resolution_id ( delegation. id ) ;
254- let prop_kind = if res. is_some_and ( |def_id| def_id == root_fn_id) {
255- PropagationKind :: Allowed
256- } else {
257- PropagationKind :: Forbidden
258- } ;
259-
260- let child = DelegationGenerics :: Default ( self . get_fn_like_generics ( root_fn_id, span) ) ;
261- let child = GenericsGenerationResult :: new ( child, prop_kind) ;
261+ let generics = self . get_fn_like_generics ( root_fn_id, span) ;
262+ let child = DelegationGenerics :: TraitImpl ( generics, child_user_specified) ;
263+ let child = GenericsGenerationResult :: new ( child) ;
262264
263265 return GenericsGenerationResults { parent, child } ;
264266 }
@@ -280,9 +282,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
280282 )
281283 } ;
282284
283- let segments = & delegation. path . segments ;
284- let len = segments. len ( ) ;
285-
286285 let can_add_generics_to_parent = len >= 2
287286 && self . get_resolution_id ( segments[ len - 2 ] . id ) . is_some_and ( |def_id| {
288287 matches ! ( self . tcx. def_kind( def_id) , DefKind :: Trait | DefKind :: TraitAlias )
@@ -302,15 +301,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
302301 DelegationGenerics :: Default ( None )
303302 } ;
304303
305- let child_generics = if segments [ len - 1 ] . args . is_some ( ) {
304+ let child_generics = if child_user_specified {
306305 DelegationGenerics :: UserSpecified
307306 } else {
308307 DelegationGenerics :: Default ( self . get_fn_like_generics ( root_fn_id, span) )
309308 } ;
310309
311310 GenericsGenerationResults {
312- parent : GenericsGenerationResult :: new ( parent_generics, PropagationKind :: Allowed ) ,
313- child : GenericsGenerationResult :: new ( child_generics, PropagationKind :: Allowed ) ,
311+ parent : GenericsGenerationResult :: new ( parent_generics) ,
312+ child : GenericsGenerationResult :: new ( child_generics) ,
314313 }
315314 }
316315
0 commit comments