Skip to content

Commit 6cb2a19

Browse files
committed
Always propagate generic params in trait impl case
1 parent 23a51f5 commit 6cb2a19

10 files changed

Lines changed: 340 additions & 687 deletions

compiler/rustc_ast_lowering/src/delegation.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -724,10 +724,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
724724
result: &mut GenericsGenerationResult<'hir>,
725725
add_lifetimes: bool,
726726
) -> hir::PathSegment<'hir> {
727-
// The second condition is needed when there is SelfAndUserSpecified case,
727+
let details = result.generics.get_args_propagation_details();
728+
729+
// The first condition is needed when there is SelfAndUserSpecified case,
728730
// we don't want to propagate generics params in this situation.
729-
let segment = if result.can_propagate()
730-
&& !result.generics.is_user_specified()
731+
let segment = if details.should_propagate
731732
&& let Some(args) = result
732733
.generics
733734
.into_hir_generics(self, item_id, span)
@@ -738,7 +739,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
738739
segment.clone()
739740
};
740741

741-
if result.generics.is_user_specified() {
742+
if details.use_args_in_sig_inheritance {
742743
result.args_segment_id = Some(segment.hir_id);
743744
}
744745

compiler/rustc_ast_lowering/src/delegation/generics.rs

Lines changed: 51 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
4645
pub(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

5250
pub(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+
5760
impl<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

135158
impl<'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

152167
impl<'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

compiler/rustc_hir_analysis/src/delegation.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,9 @@ fn create_generic_args<'tcx>(
343343
// child generics in trait.
344344
let parent = tcx.local_parent(delegation_id);
345345
parent_args = tcx.impl_trait_header(parent).trait_ref.instantiate_identity().args;
346+
347+
assert!(child_args.is_empty(), "Child args can not be used in trait impl case");
348+
346349
tcx.mk_args(&delegation_args[delegation_parent_args_count..])
347350
}
348351

0 commit comments

Comments
 (0)