Skip to content

Commit 3249fc7

Browse files
authored
Merge pull request #20725 from ChayimFriedman2/fix-missing-lifetime
fix: Fix lifetime elision handling for `Fn`-style trait bounds
2 parents 7d9af9f + ad9422d commit 3249fc7

File tree

3 files changed

+55
-25
lines changed

3 files changed

+55
-25
lines changed

crates/hir-ty/src/lower/path.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
603603
explicit_self_ty: Option<Ty>,
604604
lowering_assoc_type_generics: bool,
605605
) -> Substitution {
606-
let mut lifetime_elision = self.ctx.lifetime_elision.clone();
606+
let old_lifetime_elision = self.ctx.lifetime_elision.clone();
607607

608608
if let Some(args) = self.current_or_prev_segment.args_and_bindings
609609
&& args.parenthesized != GenericArgsParentheses::No
@@ -633,19 +633,21 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
633633
}
634634

635635
// `Fn()`-style generics are treated like functions for the purpose of lifetime elision.
636-
lifetime_elision =
636+
self.ctx.lifetime_elision =
637637
LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false };
638638
}
639639

640-
self.substs_from_args_and_bindings(
640+
let result = self.substs_from_args_and_bindings(
641641
self.current_or_prev_segment.args_and_bindings,
642642
def,
643643
infer_args,
644644
explicit_self_ty,
645645
PathGenericsSource::Segment(self.current_segment_u32()),
646646
lowering_assoc_type_generics,
647-
lifetime_elision,
648-
)
647+
self.ctx.lifetime_elision.clone(),
648+
);
649+
self.ctx.lifetime_elision = old_lifetime_elision;
650+
result
649651
}
650652

651653
pub(super) fn substs_from_args_and_bindings(

crates/hir-ty/src/lower_nextsolver/path.rs

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
616616
explicit_self_ty: Option<Ty<'db>>,
617617
lowering_assoc_type_generics: bool,
618618
) -> crate::next_solver::GenericArgs<'db> {
619-
let mut lifetime_elision = self.ctx.lifetime_elision.clone();
619+
let old_lifetime_elision = self.ctx.lifetime_elision.clone();
620620

621621
if let Some(args) = self.current_or_prev_segment.args_and_bindings
622622
&& args.parenthesized != GenericArgsParentheses::No
@@ -646,19 +646,21 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
646646
}
647647

648648
// `Fn()`-style generics are treated like functions for the purpose of lifetime elision.
649-
lifetime_elision =
649+
self.ctx.lifetime_elision =
650650
LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false };
651651
}
652652

653-
self.substs_from_args_and_bindings(
653+
let result = self.substs_from_args_and_bindings(
654654
self.current_or_prev_segment.args_and_bindings,
655655
def,
656656
infer_args,
657657
explicit_self_ty,
658658
PathGenericsSource::Segment(self.current_segment_u32()),
659659
lowering_assoc_type_generics,
660-
lifetime_elision,
661-
)
660+
self.ctx.lifetime_elision.clone(),
661+
);
662+
self.ctx.lifetime_elision = old_lifetime_elision;
663+
result
662664
}
663665

664666
pub(super) fn substs_from_args_and_bindings(
@@ -915,22 +917,36 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
915917
binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
916918
);
917919
if let Some(type_ref) = binding.type_ref {
918-
match (&self.ctx.store[type_ref], self.ctx.impl_trait_mode.mode) {
919-
(TypeRef::ImplTrait(_), ImplTraitLoweringMode::Disallowed) => (),
920-
(_, ImplTraitLoweringMode::Disallowed | ImplTraitLoweringMode::Opaque) => {
921-
let ty = self.ctx.lower_ty(type_ref);
922-
let pred = Clause(Predicate::new(
923-
interner,
924-
Binder::dummy(rustc_type_ir::PredicateKind::Clause(
925-
rustc_type_ir::ClauseKind::Projection(ProjectionPredicate {
926-
projection_term,
927-
term: ty.into(),
928-
}),
929-
)),
930-
));
931-
predicates.push(pred);
920+
let lifetime_elision =
921+
if args_and_bindings.parenthesized == GenericArgsParentheses::ParenSugar {
922+
// `Fn()`-style generics are elided like functions. This is `Output` (we lower to it in hir-def).
923+
LifetimeElisionKind::for_fn_ret(self.ctx.interner)
924+
} else {
925+
self.ctx.lifetime_elision.clone()
926+
};
927+
self.with_lifetime_elision(lifetime_elision, |this| {
928+
match (&this.ctx.store[type_ref], this.ctx.impl_trait_mode.mode) {
929+
(TypeRef::ImplTrait(_), ImplTraitLoweringMode::Disallowed) => (),
930+
(
931+
_,
932+
ImplTraitLoweringMode::Disallowed | ImplTraitLoweringMode::Opaque,
933+
) => {
934+
let ty = this.ctx.lower_ty(type_ref);
935+
let pred = Clause(Predicate::new(
936+
interner,
937+
Binder::dummy(rustc_type_ir::PredicateKind::Clause(
938+
rustc_type_ir::ClauseKind::Projection(
939+
ProjectionPredicate {
940+
projection_term,
941+
term: ty.into(),
942+
},
943+
),
944+
)),
945+
));
946+
predicates.push(pred);
947+
}
932948
}
933-
}
949+
})
934950
}
935951
for bound in binding.bounds.iter() {
936952
predicates.extend(self.ctx.lower_type_bound(

crates/ide-diagnostics/src/handlers/missing_lifetime.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,16 @@ fn bar<const F: Foo>() {}
8888
"#,
8989
);
9090
}
91+
92+
#[test]
93+
fn fn_traits() {
94+
check_diagnostics(
95+
r#"
96+
//- minicore: fn
97+
struct WithLifetime<'a>(&'a ());
98+
99+
fn foo<T: Fn(WithLifetime) -> WithLifetime>() {}
100+
"#,
101+
);
102+
}
91103
}

0 commit comments

Comments
 (0)