Skip to content

feat: Parse generic consts #19643

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions crates/parser/src/grammar/items/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 });
}
12 changes: 12 additions & 0 deletions crates/parser/test_data/generated/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"); }
Expand Down Expand Up @@ -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");
}
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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");
}
Expand Down
42 changes: 42 additions & 0 deletions crates/parser/test_data/parser/inline/err/generic_static.rast
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
static C<i32>: u32 = 0;
44 changes: 44 additions & 0 deletions crates/parser/test_data/parser/inline/err/static_where_clause.rast
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
static C: u32 = 0
where i32: Copy;
89 changes: 89 additions & 0 deletions crates/parser/test_data/parser/inline/ok/const_where_clause.rast
Original file line number Diff line number Diff line change
@@ -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"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const C<i32>: u32 = 0
where i32: Copy;
trait Foo {
const C: i32 where i32: Copy;
}
71 changes: 71 additions & 0 deletions crates/parser/test_data/parser/inline/ok/generic_const.rast
Original file line number Diff line number Diff line change
@@ -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"
4 changes: 4 additions & 0 deletions crates/parser/test_data/parser/inline/ok/generic_const.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const C<i32>: u32 = 0;
impl Foo {
const C<'a>: &'a () = &();
}
5 changes: 3 additions & 2 deletions crates/syntax/rust.ungram
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,9 @@ VariantDef =
Const =
Attr* Visibility?
'default'?
'const' (Name | '_') ':' Type
('=' body:Expr)? ';'
'const' (Name | '_') GenericParamList? ':' Type
('=' body:Expr)?
WhereClause? ';'

Static =
Attr* Visibility?
Expand Down
7 changes: 6 additions & 1 deletion crates/syntax/src/ast/generated/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -9421,7 +9422,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> {
Expand All @@ -9445,6 +9446,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 } }
Expand Down