Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-ty/src/lower/path.rs12
-rw-r--r--crates/hir-ty/src/lower_nextsolver/path.rs56
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_lifetime.rs12
3 files changed, 55 insertions, 25 deletions
diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs
index b0132e4dcb..bc03298e3b 100644
--- a/crates/hir-ty/src/lower/path.rs
+++ b/crates/hir-ty/src/lower/path.rs
@@ -603,7 +603,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
explicit_self_ty: Option<Ty>,
lowering_assoc_type_generics: bool,
) -> Substitution {
- let mut lifetime_elision = self.ctx.lifetime_elision.clone();
+ let old_lifetime_elision = self.ctx.lifetime_elision.clone();
if let Some(args) = self.current_or_prev_segment.args_and_bindings
&& args.parenthesized != GenericArgsParentheses::No
@@ -633,19 +633,21 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
}
// `Fn()`-style generics are treated like functions for the purpose of lifetime elision.
- lifetime_elision =
+ self.ctx.lifetime_elision =
LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false };
}
- self.substs_from_args_and_bindings(
+ let result = self.substs_from_args_and_bindings(
self.current_or_prev_segment.args_and_bindings,
def,
infer_args,
explicit_self_ty,
PathGenericsSource::Segment(self.current_segment_u32()),
lowering_assoc_type_generics,
- lifetime_elision,
- )
+ self.ctx.lifetime_elision.clone(),
+ );
+ self.ctx.lifetime_elision = old_lifetime_elision;
+ result
}
pub(super) fn substs_from_args_and_bindings(
diff --git a/crates/hir-ty/src/lower_nextsolver/path.rs b/crates/hir-ty/src/lower_nextsolver/path.rs
index 7d6734303c..46dc66a8c8 100644
--- a/crates/hir-ty/src/lower_nextsolver/path.rs
+++ b/crates/hir-ty/src/lower_nextsolver/path.rs
@@ -616,7 +616,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
explicit_self_ty: Option<Ty<'db>>,
lowering_assoc_type_generics: bool,
) -> crate::next_solver::GenericArgs<'db> {
- let mut lifetime_elision = self.ctx.lifetime_elision.clone();
+ let old_lifetime_elision = self.ctx.lifetime_elision.clone();
if let Some(args) = self.current_or_prev_segment.args_and_bindings
&& args.parenthesized != GenericArgsParentheses::No
@@ -646,19 +646,21 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
}
// `Fn()`-style generics are treated like functions for the purpose of lifetime elision.
- lifetime_elision =
+ self.ctx.lifetime_elision =
LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false };
}
- self.substs_from_args_and_bindings(
+ let result = self.substs_from_args_and_bindings(
self.current_or_prev_segment.args_and_bindings,
def,
infer_args,
explicit_self_ty,
PathGenericsSource::Segment(self.current_segment_u32()),
lowering_assoc_type_generics,
- lifetime_elision,
- )
+ self.ctx.lifetime_elision.clone(),
+ );
+ self.ctx.lifetime_elision = old_lifetime_elision;
+ result
}
pub(super) fn substs_from_args_and_bindings(
@@ -915,22 +917,36 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
);
if let Some(type_ref) = binding.type_ref {
- match (&self.ctx.store[type_ref], self.ctx.impl_trait_mode.mode) {
- (TypeRef::ImplTrait(_), ImplTraitLoweringMode::Disallowed) => (),
- (_, ImplTraitLoweringMode::Disallowed | ImplTraitLoweringMode::Opaque) => {
- let ty = self.ctx.lower_ty(type_ref);
- let pred = Clause(Predicate::new(
- interner,
- Binder::dummy(rustc_type_ir::PredicateKind::Clause(
- rustc_type_ir::ClauseKind::Projection(ProjectionPredicate {
- projection_term,
- term: ty.into(),
- }),
- )),
- ));
- predicates.push(pred);
+ let lifetime_elision =
+ if args_and_bindings.parenthesized == GenericArgsParentheses::ParenSugar {
+ // `Fn()`-style generics are elided like functions. This is `Output` (we lower to it in hir-def).
+ LifetimeElisionKind::for_fn_ret(self.ctx.interner)
+ } else {
+ self.ctx.lifetime_elision.clone()
+ };
+ self.with_lifetime_elision(lifetime_elision, |this| {
+ match (&this.ctx.store[type_ref], this.ctx.impl_trait_mode.mode) {
+ (TypeRef::ImplTrait(_), ImplTraitLoweringMode::Disallowed) => (),
+ (
+ _,
+ ImplTraitLoweringMode::Disallowed | ImplTraitLoweringMode::Opaque,
+ ) => {
+ let ty = this.ctx.lower_ty(type_ref);
+ let pred = Clause(Predicate::new(
+ interner,
+ Binder::dummy(rustc_type_ir::PredicateKind::Clause(
+ rustc_type_ir::ClauseKind::Projection(
+ ProjectionPredicate {
+ projection_term,
+ term: ty.into(),
+ },
+ ),
+ )),
+ ));
+ predicates.push(pred);
+ }
}
- }
+ })
}
for bound in binding.bounds.iter() {
predicates.extend(self.ctx.lower_type_bound(
diff --git a/crates/ide-diagnostics/src/handlers/missing_lifetime.rs b/crates/ide-diagnostics/src/handlers/missing_lifetime.rs
index 76b30745a0..b07f9e68f6 100644
--- a/crates/ide-diagnostics/src/handlers/missing_lifetime.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_lifetime.rs
@@ -88,4 +88,16 @@ fn bar<const F: Foo>() {}
"#,
);
}
+
+ #[test]
+ fn fn_traits() {
+ check_diagnostics(
+ r#"
+//- minicore: fn
+struct WithLifetime<'a>(&'a ());
+
+fn foo<T: Fn(WithLifetime) -> WithLifetime>() {}
+ "#,
+ );
+ }
}