about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/validation.rs36
-rw-r--r--src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rast25
-rw-r--r--src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rs1
-rw-r--r--src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast23
-rw-r--r--src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rs1
-rw-r--r--src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rast25
-rw-r--r--src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rs1
7 files changed, 103 insertions, 9 deletions
diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs
index 13d352d3c69..85eefac734b 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs
@@ -37,6 +37,7 @@ pub(crate) fn validate(root: &SyntaxNode, errors: &mut Vec<SyntaxError>) {
                 ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, errors),
                 ast::MacroRules(it) => validate_macro_rules(it, errors),
                 ast::LetExpr(it) => validate_let_expr(it, errors),
+                ast::ImplTraitType(it) => validate_impl_object_ty(it, errors),
                 _ => (),
             }
         }
@@ -340,17 +341,34 @@ fn validate_trait_object_fn_ptr_ret_ty(ty: ast::FnPtrType, errors: &mut Vec<Synt
 
 fn validate_trait_object_ty(ty: ast::DynTraitType) -> Option<SyntaxError> {
     let tbl = ty.type_bound_list()?;
-
-    if tbl.bounds().count() > 1 {
-        let dyn_token = ty.dyn_token()?;
-        let potential_parenthesis =
-            algo::skip_trivia_token(dyn_token.prev_token()?, Direction::Prev)?;
-        let kind = potential_parenthesis.kind();
-        if !matches!(kind, T!['('] | T![<] | T![=]) {
-            return Some(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range()));
+    let bounds_count = tbl.bounds().count();
+
+    match bounds_count {
+        0 => Some(SyntaxError::new(
+            "At least one trait is required for an object type",
+            ty.syntax().text_range(),
+        )),
+        _ if bounds_count > 1 => {
+            let dyn_token = ty.dyn_token()?;
+            let preceding_token =
+                algo::skip_trivia_token(dyn_token.prev_token()?, Direction::Prev)?;
+
+            if !matches!(preceding_token.kind(), T!['('] | T![<] | T![=]) {
+                return Some(SyntaxError::new("ambiguous `+` in a type", ty.syntax().text_range()));
+            }
+            None
         }
+        _ => None,
+    }
+}
+
+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 {
+        errors.push(SyntaxError::new(
+            "At least one trait must be specified",
+            ty.syntax().text_range(),
+        ));
     }
-    None
 }
 
 fn validate_macro_rules(mac: ast::MacroRules, errors: &mut Vec<SyntaxError>) {
diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rast
new file mode 100644
index 00000000000..b31af5fbc6a
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rast
@@ -0,0 +1,25 @@
+SOURCE_FILE@0..16
+  FN@0..16
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "f"
+    PARAM_LIST@4..13
+      L_PAREN@4..5 "("
+      PARAM@5..12
+        WILDCARD_PAT@5..6
+          UNDERSCORE@5..6 "_"
+        COLON@6..7 ":"
+        WHITESPACE@7..8 " "
+        REF_TYPE@8..12
+          AMP@8..9 "&"
+          DYN_TRAIT_TYPE@9..12
+            DYN_KW@9..12 "dyn"
+            TYPE_BOUND_LIST@12..12
+      R_PAREN@12..13 ")"
+    WHITESPACE@13..14 " "
+    BLOCK_EXPR@14..16
+      STMT_LIST@14..16
+        L_CURLY@14..15 "{"
+        R_CURLY@15..16 "}"
+error 9..12: At least one trait is required for an object type
diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rs b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rs
new file mode 100644
index 00000000000..2fdbb42846b
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0224_dangling_dyn.rs
@@ -0,0 +1 @@
+fn f(_: &dyn) {}
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast
new file mode 100644
index 00000000000..2db07ae12a9
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rast
@@ -0,0 +1,23 @@
+SOURCE_FILE@0..16
+  FN@0..16
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "f"
+    PARAM_LIST@4..13
+      L_PAREN@4..5 "("
+      PARAM@5..12
+        WILDCARD_PAT@5..6
+          UNDERSCORE@5..6 "_"
+        COLON@6..7 ":"
+        WHITESPACE@7..8 " "
+        IMPL_TRAIT_TYPE@8..12
+          IMPL_KW@8..12 "impl"
+          TYPE_BOUND_LIST@12..12
+      R_PAREN@12..13 ")"
+    WHITESPACE@13..14 " "
+    BLOCK_EXPR@14..16
+      STMT_LIST@14..16
+        L_CURLY@14..15 "{"
+        R_CURLY@15..16 "}"
+error 8..12: At least one trait must be specified
diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rs b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rs
new file mode 100644
index 00000000000..61706d9e412
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl.rs
@@ -0,0 +1 @@
+fn f(_: impl) {}
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rast b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rast
new file mode 100644
index 00000000000..dbe6535ac66
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rast
@@ -0,0 +1,25 @@
+SOURCE_FILE@0..17
+  FN@0..17
+    FN_KW@0..2 "fn"
+    WHITESPACE@2..3 " "
+    NAME@3..4
+      IDENT@3..4 "f"
+    PARAM_LIST@4..14
+      L_PAREN@4..5 "("
+      PARAM@5..13
+        WILDCARD_PAT@5..6
+          UNDERSCORE@5..6 "_"
+        COLON@6..7 ":"
+        WHITESPACE@7..8 " "
+        REF_TYPE@8..13
+          AMP@8..9 "&"
+          IMPL_TRAIT_TYPE@9..13
+            IMPL_KW@9..13 "impl"
+            TYPE_BOUND_LIST@13..13
+      R_PAREN@13..14 ")"
+    WHITESPACE@14..15 " "
+    BLOCK_EXPR@15..17
+      STMT_LIST@15..17
+        L_CURLY@15..16 "{"
+        R_CURLY@16..17 "}"
+error 9..13: At least one trait must be specified
diff --git a/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rs b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rs
new file mode 100644
index 00000000000..0b440b4c5af
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/dangling_impl_reference.rs
@@ -0,0 +1 @@
+fn f(_: &impl) {}
\ No newline at end of file