From 0f0276a858d7e481dfab88a46feeeb9de752ec49 Mon Sep 17 00:00:00 2001 From: Alyssa Haroldsen Date: Mon, 1 Jun 2026 14:17:45 -0700 Subject: [PATCH] Parse unnamed enum variants As of writing, this is still rejected by rustc at a later stage. --- crates/parser/src/grammar/items/adt.rs | 31 ++++++++++--------- .../test_data/parser/ok/0019_enums.rast | 10 ++++++ .../parser/test_data/parser/ok/0019_enums.rs | 1 + crates/syntax/rust.ungram | 2 +- crates/syntax/src/ast/generated/nodes.rs | 2 ++ 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/crates/parser/src/grammar/items/adt.rs b/crates/parser/src/grammar/items/adt.rs index a030190ad34b..33e19f5725b3 100644 --- a/crates/parser/src/grammar/items/adt.rs +++ b/crates/parser/src/grammar/items/adt.rs @@ -87,24 +87,27 @@ pub(crate) fn variant_list(p: &mut Parser<'_>) { attributes::outer_attrs(p); if p.at(IDENT) { name(p); - match p.current() { - T!['{'] => record_field_list(p), - T!['('] => tuple_field_list(p), - _ => (), - } - - // test variant_discriminant - // enum E { X(i32) = 10 } - if p.eat(T![=]) { - let m = p.start(); - expressions::expr(p); - m.complete(p, CONST_ARG); - } - m.complete(p, VARIANT); + } else if p.at(T![_]) { + p.bump(T![_]); } else { m.abandon(p); p.err_and_bump("expected enum variant"); + return; + } + match p.current() { + T!['{'] => record_field_list(p), + T!['('] => tuple_field_list(p), + _ => (), + } + + // test variant_discriminant + // enum E { X(i32) = 10 } + if p.eat(T![=]) { + let m = p.start(); + expressions::expr(p); + m.complete(p, CONST_ARG); } + m.complete(p, VARIANT); } } diff --git a/crates/parser/test_data/parser/ok/0019_enums.rast b/crates/parser/test_data/parser/ok/0019_enums.rast index 51837e5372a7..24256ea29436 100644 --- a/crates/parser/test_data/parser/ok/0019_enums.rast +++ b/crates/parser/test_data/parser/ok/0019_enums.rast @@ -151,6 +151,16 @@ SOURCE_FILE L_PAREN "(" R_PAREN ")" COMMA "," + WHITESPACE "\n " + VARIANT + UNDERSCORE "_" + WHITESPACE " " + EQ "=" + WHITESPACE " " + CONST_ARG + RANGE_EXPR + DOT2 ".." + COMMA "," WHITESPACE "\n" R_CURLY "}" WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/ok/0019_enums.rs b/crates/parser/test_data/parser/ok/0019_enums.rs index 7a1afa0e62f1..f548479e45d8 100644 --- a/crates/parser/test_data/parser/ok/0019_enums.rs +++ b/crates/parser/test_data/parser/ok/0019_enums.rs @@ -22,4 +22,5 @@ enum E5 { F {}, D(u32,), E(), + _ = .., } diff --git a/crates/syntax/rust.ungram b/crates/syntax/rust.ungram index 408f2f4b32c7..af50ed165619 100644 --- a/crates/syntax/rust.ungram +++ b/crates/syntax/rust.ungram @@ -305,7 +305,7 @@ VariantList = Variant = Attr* Visibility? - Name FieldList? ('=' ConstArg)? + (Name | '_') FieldList? ('=' ConstArg)? Union = Attr* Visibility? diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index c18311bfa3ad..71f23fe08750 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -2059,6 +2059,8 @@ impl Variant { pub fn field_list(&self) -> Option { support::child(&self.syntax) } #[inline] pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } + #[inline] + pub fn underscore_token(&self) -> Option { support::token(&self.syntax, T![_]) } } pub struct VariantList { pub(crate) syntax: SyntaxNode,