Skip to content

Commit 3d486d2

Browse files
Rollup merge of #153705 - aerooneqq:delegation-impl-trait-generics, r=petrochenkov
Always generate generics in delegation that match trait in trait impl scenario After #151864 there is a change in delegation code generation in `trait impl` cases: after #151864 we started to look at user-specified args and generate functions, whose generics may not match the signature of the function that is defined in trait. Such handling of delegation from trait impl is not correct, as the generated function should always have the same generics as its signature function in trait. This addresses the "Fix generic params generation in trait impl case" future work from #151864 r? @petrochenkov
2 parents d097a0c + d87d7b9 commit 3d486d2

File tree

7 files changed

+340
-136
lines changed

7 files changed

+340
-136
lines changed

compiler/rustc_ast_lowering/src/delegation.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -725,9 +725,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
725725
result: &mut GenericsGenerationResult<'hir>,
726726
add_lifetimes: bool,
727727
) -> hir::PathSegment<'hir> {
728+
let details = result.generics.args_propagation_details();
729+
728730
// The first condition is needed when there is SelfAndUserSpecified case,
729731
// we don't want to propagate generics params in this situation.
730-
let segment = if !result.generics.is_user_specified()
732+
let segment = if details.should_propagate
731733
&& let Some(args) = result
732734
.generics
733735
.into_hir_generics(self, item_id, span)
@@ -738,7 +740,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
738740
segment.clone()
739741
};
740742

741-
if result.generics.is_user_specified() {
743+
if details.use_args_in_sig_inheritance {
742744
result.args_segment_id = Some(segment.hir_id);
743745
}
744746

compiler/rustc_ast_lowering/src/delegation/generics.rs

Lines changed: 63 additions & 18 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
@@ -48,12 +52,29 @@ pub(super) struct GenericsGenerationResults<'hir> {
4852
pub(super) child: GenericsGenerationResult<'hir>,
4953
}
5054

55+
pub(super) struct GenericArgsPropagationDetails {
56+
pub(super) should_propagate: bool,
57+
pub(super) use_args_in_sig_inheritance: bool,
58+
}
59+
5160
impl<T> DelegationGenerics<T> {
52-
fn is_user_specified(&self) -> bool {
53-
matches!(
54-
self,
55-
DelegationGenerics::UserSpecified | DelegationGenerics::SelfAndUserSpecified { .. }
56-
)
61+
fn 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+
}
5778
}
5879
}
5980

@@ -77,6 +98,12 @@ impl<'hir> HirOrAstGenerics<'hir> {
7798
DelegationGenerics::SelfAndUserSpecified(generics) => {
7899
DelegationGenerics::SelfAndUserSpecified(generics.as_mut().map(process_params))
79100
}
101+
DelegationGenerics::TraitImpl(generics, user_specified) => {
102+
DelegationGenerics::TraitImpl(
103+
generics.as_mut().map(process_params),
104+
*user_specified,
105+
)
106+
}
80107
};
81108

82109
*self = HirOrAstGenerics::Hir(hir_generics);
@@ -91,7 +118,8 @@ impl<'hir> HirOrAstGenerics<'hir> {
91118
HirOrAstGenerics::Hir(hir_generics) => match hir_generics {
92119
DelegationGenerics::UserSpecified => hir::Generics::empty(),
93120
DelegationGenerics::Default(generics)
94-
| DelegationGenerics::SelfAndUserSpecified(generics) => {
121+
| DelegationGenerics::SelfAndUserSpecified(generics)
122+
| DelegationGenerics::TraitImpl(generics, _) => {
95123
generics.unwrap_or(hir::Generics::empty())
96124
}
97125
},
@@ -111,17 +139,18 @@ impl<'hir> HirOrAstGenerics<'hir> {
111139
HirOrAstGenerics::Hir(hir_generics) => match hir_generics {
112140
DelegationGenerics::UserSpecified => None,
113141
DelegationGenerics::Default(generics)
114-
| DelegationGenerics::SelfAndUserSpecified(generics) => generics.map(|generics| {
142+
| DelegationGenerics::SelfAndUserSpecified(generics)
143+
| DelegationGenerics::TraitImpl(generics, _) => generics.map(|generics| {
115144
ctx.create_generics_args_from_params(generics.params, add_lifetimes, span)
116145
}),
117146
},
118147
}
119148
}
120149

121-
pub(super) fn is_user_specified(&self) -> bool {
150+
pub(super) fn args_propagation_details(&self) -> GenericArgsPropagationDetails {
122151
match self {
123-
HirOrAstGenerics::Ast(ast_generics) => ast_generics.is_user_specified(),
124-
HirOrAstGenerics::Hir(hir_generics) => hir_generics.is_user_specified(),
152+
HirOrAstGenerics::Ast(ast_generics) => ast_generics.args_propagation_details(),
153+
HirOrAstGenerics::Hir(hir_generics) => hir_generics.args_propagation_details(),
125154
}
126155
}
127156
}
@@ -215,10 +244,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
215244
item_id: NodeId,
216245
span: Span,
217246
) -> GenericsGenerationResults<'hir> {
218-
let delegation_in_free_ctx = !matches!(
219-
self.tcx.def_kind(self.tcx.local_parent(self.local_def_id(item_id))),
220-
DefKind::Trait | DefKind::Impl { .. }
221-
);
247+
let delegation_parent_kind =
248+
self.tcx.def_kind(self.tcx.local_parent(self.local_def_id(item_id)));
249+
250+
let segments = &delegation.path.segments;
251+
let len = segments.len();
252+
let child_user_specified = segments[len - 1].args.is_some();
253+
254+
// If we are in trait impl always generate function whose generics matches
255+
// those that are defined in trait.
256+
if matches!(delegation_parent_kind, DefKind::Impl { of_trait: true }) {
257+
// Considering parent generics, during signature inheritance
258+
// we will take those args that are in trait impl header trait ref.
259+
let parent = GenericsGenerationResult::new(DelegationGenerics::Default(None));
260+
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);
264+
265+
return GenericsGenerationResults { parent, child };
266+
}
267+
268+
let delegation_in_free_ctx =
269+
!matches!(delegation_parent_kind, DefKind::Trait | DefKind::Impl { .. });
222270

223271
let root_function_in_trait =
224272
matches!(self.tcx.def_kind(self.tcx.parent(root_fn_id)), DefKind::Trait);
@@ -234,9 +282,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
234282
)
235283
};
236284

237-
let segments = &delegation.path.segments;
238-
let len = segments.len();
239-
240285
let can_add_generics_to_parent = len >= 2
241286
&& self.get_resolution_id(segments[len - 2].id).is_some_and(|def_id| {
242287
matches!(self.tcx.def_kind(def_id), DefKind::Trait | DefKind::TraitAlias)
@@ -256,7 +301,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
256301
DelegationGenerics::Default(None)
257302
};
258303

259-
let child_generics = if segments[len - 1].args.is_some() {
304+
let child_generics = if child_user_specified {
260305
DelegationGenerics::UserSpecified
261306
} else {
262307
DelegationGenerics::Default(self.get_fn_like_generics(root_fn_id, span))

compiler/rustc_hir_analysis/src/delegation.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,10 +339,14 @@ fn create_generic_args<'tcx>(
339339
| (FnKind::AssocTrait, FnKind::AssocTrait) => delegation_args,
340340

341341
(FnKind::AssocTraitImpl, FnKind::AssocTrait) => {
342-
// Special case, as user specifies Trait args in impl trait header, we want to treat
343-
// them as parent args.
342+
// Special case, as user specifies Trait args in trait impl header, we want to treat
343+
// them as parent args. We always generate a function whose generics match
344+
// child generics in trait.
344345
let parent = tcx.local_parent(delegation_id);
345346
parent_args = tcx.impl_trait_header(parent).trait_ref.instantiate_identity().args;
347+
348+
assert!(child_args.is_empty(), "Child args can not be used in trait impl case");
349+
346350
tcx.mk_args(&delegation_args[delegation_parent_args_count..])
347351
}
348352

tests/ui/delegation/generics/impl-trait-wrong-args-count.rs

Lines changed: 0 additions & 40 deletions
This file was deleted.

tests/ui/delegation/generics/impl-trait-wrong-args-count.stderr

Lines changed: 0 additions & 74 deletions
This file was deleted.

0 commit comments

Comments
 (0)