Parse generic consts

A lang team experiment, https://github.com/rust-lang/rust/issues/113521.
This commit is contained in:
Chayim Refael Friedman 2025-04-21 02:11:56 +03:00
parent 2f2cff19f8
commit 812a035689
12 changed files with 305 additions and 3 deletions

View file

@ -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 });
}

View file

@ -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");
}

View file

@ -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

View file

@ -0,0 +1 @@
static C<i32>: u32 = 0;

View file

@ -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

View file

@ -0,0 +1,2 @@
static C: u32 = 0
where i32: Copy;

View file

@ -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"

View file

@ -0,0 +1,5 @@
const C<i32>: u32 = 0
where i32: Copy;
trait Foo {
const C: i32 where i32: Copy;
}

View file

@ -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"

View file

@ -0,0 +1,4 @@
const C<i32>: u32 = 0;
impl Foo {
const C<'a>: &'a () = &();
}

View file

@ -287,8 +287,9 @@ VariantDef =
Const =
Attr* Visibility?
'default'?
'const' (Name | '_') ':' Type
('=' body:Expr)? ';'
'const' (Name | '_') GenericParamList? ':' Type
('=' body:Expr)?
WhereClause? ';'
Static =
Attr* Visibility?

View file

@ -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 {
@ -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> {
@ -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 } }