about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs56
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_lifetime.rs12
3 files changed, 55 insertions, 25 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs
index b0132e4dcbc..bc03298e3bb 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs
index 7d6734303c4..46dc66a8c8b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower_nextsolver/path.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_lifetime.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_lifetime.rs
index 76b30745a04..b07f9e68f63 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_lifetime.rs
+++ b/src/tools/rust-analyzer/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>() {}
+        "#,
+        );
+    }
 }