Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/parser/src/grammar/items/consts.rs26
-rw-r--r--crates/parser/test_data/generated/runner.rs12
-rw-r--r--crates/parser/test_data/parser/inline/err/generic_static.rast42
-rw-r--r--crates/parser/test_data/parser/inline/err/generic_static.rs1
-rw-r--r--crates/parser/test_data/parser/inline/err/static_where_clause.rast44
-rw-r--r--crates/parser/test_data/parser/inline/err/static_where_clause.rs2
-rw-r--r--crates/parser/test_data/parser/inline/ok/const_where_clause.rast89
-rw-r--r--crates/parser/test_data/parser/inline/ok/const_where_clause.rs5
-rw-r--r--crates/parser/test_data/parser/inline/ok/generic_const.rast71
-rw-r--r--crates/parser/test_data/parser/inline/ok/generic_const.rs4
-rw-r--r--crates/syntax/rust.ungram5
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs7
12 files changed, 305 insertions, 3 deletions
diff --git a/crates/parser/src/grammar/items/consts.rs b/crates/parser/src/grammar/items/consts.rs
index 9549ec9b40..8e255985a2 100644
--- a/crates/parser/src/grammar/items/consts.rs
+++ b/crates/parser/src/grammar/items/consts.rs
@@ -24,6 +24,18 @@ fn const_or_static(p: &mut Parser<'_>, m: Marker, is_const: bool) {
name(p);
}
+ // FIXME: Recover on statics with generic params/where clause.
+ if is_const {
+ // test generic_const
+ // const C<i32>: u32 = 0;
+ // impl Foo {
+ // const C<'a>: &'a () = &();
+ // }
+ generic_params::opt_generic_param_list(p);
+ }
+ // test_err generic_static
+ // static C<i32>: u32 = 0;
+
if p.at(T![:]) {
types::ascription(p);
} else {
@@ -32,6 +44,20 @@ fn const_or_static(p: &mut Parser<'_>, m: Marker, is_const: bool) {
if p.eat(T![=]) {
expressions::expr(p);
}
+
+ if is_const {
+ // test const_where_clause
+ // const C<i32>: u32 = 0
+ // where i32: Copy;
+ // trait Foo {
+ // const C: i32 where i32: Copy;
+ // }
+ generic_params::opt_where_clause(p);
+ }
+ // test_err static_where_clause
+ // static C: u32 = 0
+ // where i32: Copy;
+
p.expect(T![;]);
m.complete(p, if is_const { CONST } else { STATIC });
}
diff --git a/crates/parser/test_data/generated/runner.rs b/crates/parser/test_data/generated/runner.rs
index 2ea29345ed..87ffc99539 100644
--- a/crates/parser/test_data/generated/runner.rs
+++ b/crates/parser/test_data/generated/runner.rs
@@ -139,6 +139,10 @@ mod ok {
run_and_expect_no_errors("test_data/parser/inline/ok/const_trait_bound.rs");
}
#[test]
+ fn const_where_clause() {
+ run_and_expect_no_errors("test_data/parser/inline/ok/const_where_clause.rs");
+ }
+ #[test]
fn continue_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/continue_expr.rs"); }
#[test]
fn crate_path() { run_and_expect_no_errors("test_data/parser/inline/ok/crate_path.rs"); }
@@ -278,6 +282,8 @@ mod ok {
run_and_expect_no_errors("test_data/parser/inline/ok/generic_arg_bounds.rs");
}
#[test]
+ fn generic_const() { run_and_expect_no_errors("test_data/parser/inline/ok/generic_const.rs"); }
+ #[test]
fn generic_param_attribute() {
run_and_expect_no_errors("test_data/parser/inline/ok/generic_param_attribute.rs");
}
@@ -764,6 +770,8 @@ mod err {
run_and_expect_errors("test_data/parser/inline/err/generic_param_list_recover.rs");
}
#[test]
+ fn generic_static() { run_and_expect_errors("test_data/parser/inline/err/generic_static.rs"); }
+ #[test]
fn impl_type() { run_and_expect_errors("test_data/parser/inline/err/impl_type.rs"); }
#[test]
fn let_else_right_curly_brace() {
@@ -836,6 +844,10 @@ mod err {
run_and_expect_errors("test_data/parser/inline/err/recover_from_missing_const_default.rs");
}
#[test]
+ fn static_where_clause() {
+ run_and_expect_errors("test_data/parser/inline/err/static_where_clause.rs");
+ }
+ #[test]
fn struct_field_recover() {
run_and_expect_errors("test_data/parser/inline/err/struct_field_recover.rs");
}
diff --git a/crates/parser/test_data/parser/inline/err/generic_static.rast b/crates/parser/test_data/parser/inline/err/generic_static.rast
new file mode 100644
index 0000000000..485ad11f23
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/generic_static.rast
@@ -0,0 +1,42 @@
+SOURCE_FILE
+ STATIC
+ STATIC_KW "static"
+ WHITESPACE " "
+ NAME
+ IDENT "C"
+ ERROR
+ L_ANGLE "<"
+ ERROR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ ERROR
+ R_ANGLE ">"
+ ERROR
+ COLON ":"
+ WHITESPACE " "
+ ERROR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "u32"
+ WHITESPACE " "
+ ERROR
+ EQ "="
+ WHITESPACE " "
+ ERROR
+ INT_NUMBER "0"
+ ERROR
+ SEMICOLON ";"
+ WHITESPACE "\n"
+error 8: missing type for `const` or `static`
+error 8: expected SEMICOLON
+error 8: expected an item
+error 12: expected an item
+error 12: expected an item
+error 13: expected an item
+error 18: expected an item
+error 19: expected an item
+error 21: expected an item
+error 22: expected an item
diff --git a/crates/parser/test_data/parser/inline/err/generic_static.rs b/crates/parser/test_data/parser/inline/err/generic_static.rs
new file mode 100644
index 0000000000..d76aa7a205
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/generic_static.rs
@@ -0,0 +1 @@
+static C<i32>: u32 = 0;
diff --git a/crates/parser/test_data/parser/inline/err/static_where_clause.rast b/crates/parser/test_data/parser/inline/err/static_where_clause.rast
new file mode 100644
index 0000000000..cde3e47ad5
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/static_where_clause.rast
@@ -0,0 +1,44 @@
+SOURCE_FILE
+ STATIC
+ STATIC_KW "static"
+ WHITESPACE " "
+ NAME
+ IDENT "C"
+ COLON ":"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "u32"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "0"
+ WHITESPACE "\n"
+ ERROR
+ WHERE_KW "where"
+ WHITESPACE " "
+ ERROR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ ERROR
+ COLON ":"
+ WHITESPACE " "
+ ERROR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Copy"
+ ERROR
+ SEMICOLON ";"
+ WHITESPACE "\n"
+error 17: expected SEMICOLON
+error 18: expected an item
+error 27: expected an item
+error 27: expected an item
+error 33: expected an item
+error 33: expected an item
diff --git a/crates/parser/test_data/parser/inline/err/static_where_clause.rs b/crates/parser/test_data/parser/inline/err/static_where_clause.rs
new file mode 100644
index 0000000000..c330f35da2
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/err/static_where_clause.rs
@@ -0,0 +1,2 @@
+static C: u32 = 0
+where i32: Copy;
diff --git a/crates/parser/test_data/parser/inline/ok/const_where_clause.rast b/crates/parser/test_data/parser/inline/ok/const_where_clause.rast
new file mode 100644
index 0000000000..12148f6afe
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/const_where_clause.rast
@@ -0,0 +1,89 @@
+SOURCE_FILE
+ CONST
+ CONST_KW "const"
+ WHITESPACE " "
+ NAME
+ IDENT "C"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ TYPE_PARAM
+ NAME
+ IDENT "i32"
+ R_ANGLE ">"
+ COLON ":"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "u32"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "0"
+ WHITESPACE "\n"
+ WHERE_CLAUSE
+ WHERE_KW "where"
+ WHITESPACE " "
+ WHERE_PRED
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ COLON ":"
+ WHITESPACE " "
+ TYPE_BOUND_LIST
+ TYPE_BOUND
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Copy"
+ SEMICOLON ";"
+ WHITESPACE "\n"
+ TRAIT
+ TRAIT_KW "trait"
+ WHITESPACE " "
+ NAME
+ IDENT "Foo"
+ WHITESPACE " "
+ ASSOC_ITEM_LIST
+ L_CURLY "{"
+ WHITESPACE "\n "
+ CONST
+ CONST_KW "const"
+ WHITESPACE " "
+ NAME
+ IDENT "C"
+ COLON ":"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ WHITESPACE " "
+ WHERE_CLAUSE
+ WHERE_KW "where"
+ WHITESPACE " "
+ WHERE_PRED
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "i32"
+ COLON ":"
+ WHITESPACE " "
+ TYPE_BOUND_LIST
+ TYPE_BOUND
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Copy"
+ SEMICOLON ";"
+ WHITESPACE "\n"
+ R_CURLY "}"
+ WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/inline/ok/const_where_clause.rs b/crates/parser/test_data/parser/inline/ok/const_where_clause.rs
new file mode 100644
index 0000000000..5ad4b2fe83
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/const_where_clause.rs
@@ -0,0 +1,5 @@
+const C<i32>: u32 = 0
+where i32: Copy;
+trait Foo {
+ const C: i32 where i32: Copy;
+}
diff --git a/crates/parser/test_data/parser/inline/ok/generic_const.rast b/crates/parser/test_data/parser/inline/ok/generic_const.rast
new file mode 100644
index 0000000000..bf432b99b9
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/generic_const.rast
@@ -0,0 +1,71 @@
+SOURCE_FILE
+ CONST
+ CONST_KW "const"
+ WHITESPACE " "
+ NAME
+ IDENT "C"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ TYPE_PARAM
+ NAME
+ IDENT "i32"
+ R_ANGLE ">"
+ COLON ":"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "u32"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "0"
+ SEMICOLON ";"
+ WHITESPACE "\n"
+ IMPL
+ IMPL_KW "impl"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Foo"
+ WHITESPACE " "
+ ASSOC_ITEM_LIST
+ L_CURLY "{"
+ WHITESPACE "\n "
+ CONST
+ CONST_KW "const"
+ WHITESPACE " "
+ NAME
+ IDENT "C"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
+ COLON ":"
+ WHITESPACE " "
+ REF_TYPE
+ AMP "&"
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ WHITESPACE " "
+ TUPLE_TYPE
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ REF_EXPR
+ AMP "&"
+ TUPLE_EXPR
+ L_PAREN "("
+ R_PAREN ")"
+ SEMICOLON ";"
+ WHITESPACE "\n"
+ R_CURLY "}"
+ WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/inline/ok/generic_const.rs b/crates/parser/test_data/parser/inline/ok/generic_const.rs
new file mode 100644
index 0000000000..ce718a4628
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/generic_const.rs
@@ -0,0 +1,4 @@
+const C<i32>: u32 = 0;
+impl Foo {
+ const C<'a>: &'a () = &();
+}
diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram
index a055ed7f2f..a0ae0d6858 100644
--- a/crates/syntax/rust.ungram
+++ b/crates/syntax/rust.ungram
@@ -287,8 +287,9 @@ VariantDef =
Const =
Attr* Visibility?
'default'?
- 'const' (Name | '_') ':' Type
- ('=' body:Expr)? ';'
+ 'const' (Name | '_') GenericParamList? ':' Type
+ ('=' body:Expr)?
+ WhereClause? ';'
Static =
Attr* Visibility?
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 83ef2d2428..1243f6418f 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -405,6 +405,7 @@ pub struct Const {
}
impl ast::HasAttrs for Const {}
impl ast::HasDocComments for Const {}
+impl ast::HasGenericParams for Const {}
impl ast::HasName for Const {}
impl ast::HasVisibility for Const {}
impl Const {
@@ -9423,7 +9424,7 @@ impl ast::HasGenericParams for AnyHasGenericParams {}
impl AstNode for AnyHasGenericParams {
#[inline]
fn can_cast(kind: SyntaxKind) -> bool {
- matches!(kind, ENUM | FN | IMPL | STRUCT | TRAIT | TRAIT_ALIAS | TYPE_ALIAS | UNION)
+ matches!(kind, CONST | ENUM | FN | IMPL | STRUCT | TRAIT | TRAIT_ALIAS | TYPE_ALIAS | UNION)
}
#[inline]
fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -9447,6 +9448,10 @@ impl fmt::Debug for AnyHasGenericParams {
f.debug_struct("AnyHasGenericParams").field("syntax", &self.syntax).finish()
}
}
+impl From<Const> for AnyHasGenericParams {
+ #[inline]
+ fn from(node: Const) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
+}
impl From<Enum> for AnyHasGenericParams {
#[inline]
fn from(node: Enum) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }