about summary refs log tree commit diff
path: root/src/tools/rust-analyzer
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2025-03-25 07:49:45 +0000
committerGitHub <noreply@github.com>2025-03-25 07:49:45 +0000
commitc7509abf6f776e4277f6a9721a85fe5d99f9c53e (patch)
treef7821ab624bbf90937540a0deff5483aa8862584 /src/tools/rust-analyzer
parent51d3d8cfb1445eeaa9db819acfb3fe333b085eaa (diff)
parentd59743101d06c026cee1edeac2683558dd6484c3 (diff)
downloadrust-c7509abf6f776e4277f6a9721a85fe5d99f9c53e.tar.gz
rust-c7509abf6f776e4277f6a9721a85fe5d99f9c53e.zip
Merge pull request #19347 from Shourya742/2025-03-13-add-diagnostic-for-dnagling-impl-with-lifetime
Add diagnostic for missing ambiguity error for impl trait
Diffstat (limited to 'src/tools/rust-analyzer')
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/validation.rs31
-rw-r--r--src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rast38
-rw-r--r--src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rs1
-rw-r--r--src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rast29
-rw-r--r--src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rs1
5 files changed, 99 insertions, 1 deletions
diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs
index 14df485a9d4..12894a2bda8 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs
@@ -363,11 +363,40 @@ fn validate_trait_object_ty(ty: ast::DynTraitType) -> Option<SyntaxError> {
 }
 
 fn validate_impl_object_ty(ty: ast::ImplTraitType, errors: &mut Vec<SyntaxError>) {
-    if ty.type_bound_list().map_or(0, |tbl| tbl.bounds().count()) == 0 {
+    let Some(bound_list) = ty.type_bound_list() else {
         errors.push(SyntaxError::new(
             "At least one trait must be specified",
             ty.syntax().text_range(),
         ));
+        return;
+    };
+
+    let bounds: Vec<_> = bound_list.bounds().collect();
+
+    if !bounds.iter().any(|b| !matches!(b.kind(), ast::TypeBoundKind::Lifetime(_))) {
+        errors.push(SyntaxError::new(
+            "At least one trait must be specified",
+            ty.syntax().text_range(),
+        ));
+        return;
+    }
+
+    if bounds.len() == 1 {
+        return;
+    }
+
+    let Some(preceding_token) = ty
+        .impl_token()
+        .and_then(|token| token.prev_token())
+        .and_then(|prev| algo::skip_trivia_token(prev, Direction::Prev))
+    else {
+        return;
+    };
+
+    if !matches!(preceding_token.kind(), T!['('] | T![<] | T![=])
+        && matches!(preceding_token.kind(), T![&])
+    {
+        errors.push(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range()));
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rast
new file mode 100644
index 00000000000..bd71c61cada
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rast
@@ -0,0 +1,38 @@
+SOURCE_FILE@0..28
+  FN@0..28
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "f"
+    PARAM_LIST@4..25
+      L_PAREN@4..5 "("
+      PARAM@5..24
+        WILDCARD_PAT@5..6
+          UNDERSCORE@5..6 "_"
+        COLON@6..7 ":"
+        WHITESPACE@7..8 " "
+        REF_TYPE@8..24
+          AMP@8..9 "&"
+          IMPL_TRAIT_TYPE@9..24
+            IMPL_KW@9..13 "impl"
+            WHITESPACE@13..14 " "
+            TYPE_BOUND_LIST@14..24
+              TYPE_BOUND@14..16
+                LIFETIME@14..16
+                  LIFETIME_IDENT@14..16 "'a"
+              WHITESPACE@16..17 " "
+              PLUS@17..18 "+"
+              WHITESPACE@18..19 " "
+              TYPE_BOUND@19..24
+                PATH_TYPE@19..24
+                  PATH@19..24
+                    PATH_SEGMENT@19..24
+                      NAME_REF@19..24
+                        IDENT@19..24 "Sized"
+      R_PAREN@24..25 ")"
+    WHITESPACE@25..26 " "
+    BLOCK_EXPR@26..28
+      STMT_LIST@26..28
+        L_CURLY@26..27 "{"
+        R_CURLY@27..28 "}"
+error 9..24: ambiguous `+` in a type
diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rs b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rs
new file mode 100644
index 00000000000..670a6f0ea7c
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0261_dangling_impl_undeclared_lifetime.rs
@@ -0,0 +1 @@
+fn f(_: &impl 'a + Sized) {}
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rast
new file mode 100644
index 00000000000..98aa862bc88
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rast
@@ -0,0 +1,29 @@
+SOURCE_FILE@0..20
+  FN@0..20
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "f"
+    PARAM_LIST@4..17
+      L_PAREN@4..5 "("
+      PARAM@5..16
+        WILDCARD_PAT@5..6
+          UNDERSCORE@5..6 "_"
+        COLON@6..7 ":"
+        WHITESPACE@7..8 " "
+        REF_TYPE@8..16
+          AMP@8..9 "&"
+          IMPL_TRAIT_TYPE@9..16
+            IMPL_KW@9..13 "impl"
+            WHITESPACE@13..14 " "
+            TYPE_BOUND_LIST@14..16
+              TYPE_BOUND@14..16
+                LIFETIME@14..16
+                  LIFETIME_IDENT@14..16 "'a"
+      R_PAREN@16..17 ")"
+    WHITESPACE@17..18 " "
+    BLOCK_EXPR@18..20
+      STMT_LIST@18..20
+        L_CURLY@18..19 "{"
+        R_CURLY@19..20 "}"
+error 9..16: At least one trait must be specified
diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rs b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rs
new file mode 100644
index 00000000000..5b18a54ef5a
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/impl_trait_lifetime_only.rs
@@ -0,0 +1 @@
+fn f(_: &impl 'a) {}
\ No newline at end of file