Merge pull request #18453 from ChayimFriedman2/leading-or

Parse patterns with leading pipe properly in all places
This commit is contained in:
Lukas Wirth 2024-10-31 14:49:35 +00:00 committed by GitHub
commit a5b5b466b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 73 additions and 16 deletions

View File

@ -67,7 +67,7 @@ pub(crate) fn pat(p: &mut Parser<'_>) {
} }
pub(crate) fn pat_top(p: &mut Parser<'_>) { pub(crate) fn pat_top(p: &mut Parser<'_>) {
patterns::pattern_top(p); patterns::pattern(p);
} }
pub(crate) fn ty(p: &mut Parser<'_>) { pub(crate) fn ty(p: &mut Parser<'_>) {
@ -117,7 +117,7 @@ pub(crate) fn macro_items(p: &mut Parser<'_>) {
pub(crate) fn pattern(p: &mut Parser<'_>) { pub(crate) fn pattern(p: &mut Parser<'_>) {
let m = p.start(); let m = p.start();
patterns::pattern_top(p); patterns::pattern(p);
if p.at(EOF) { if p.at(EOF) {
m.abandon(p); m.abandon(p);
return; return;

View File

@ -660,7 +660,7 @@ fn for_expr(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
fn let_expr(p: &mut Parser<'_>) -> CompletedMarker { fn let_expr(p: &mut Parser<'_>) -> CompletedMarker {
let m = p.start(); let m = p.start();
p.bump(T![let]); p.bump(T![let]);
patterns::pattern_top(p); patterns::pattern(p);
p.expect(T![=]); p.expect(T![=]);
expr_let(p); expr_let(p);
m.complete(p, LET_EXPR) m.complete(p, LET_EXPR)

View File

@ -20,14 +20,9 @@
const RANGE_PAT_END_FIRST: TokenSet = const RANGE_PAT_END_FIRST: TokenSet =
expressions::LITERAL_FIRST.union(paths::PATH_FIRST).union(TokenSet::new(&[T![-], T![const]])); expressions::LITERAL_FIRST.union(paths::PATH_FIRST).union(TokenSet::new(&[T![-], T![const]]));
pub(crate) fn pattern(p: &mut Parser<'_>) {
let m = p.start();
pattern_r(p, m, false, PAT_RECOVERY_SET);
}
/// Parses a pattern list separated by pipes `|`. /// Parses a pattern list separated by pipes `|`.
pub(super) fn pattern_top(p: &mut Parser<'_>) { pub(crate) fn pattern(p: &mut Parser<'_>) {
pattern_top_r(p, PAT_RECOVERY_SET); pattern_r(p, PAT_RECOVERY_SET);
} }
pub(crate) fn pattern_single(p: &mut Parser<'_>) { pub(crate) fn pattern_single(p: &mut Parser<'_>) {
@ -37,9 +32,7 @@ pub(crate) fn pattern_single(p: &mut Parser<'_>) {
/// Parses a pattern list separated by pipes `|` /// Parses a pattern list separated by pipes `|`
/// using the given `recovery_set`. /// using the given `recovery_set`.
pub(super) fn pattern_top_r(p: &mut Parser<'_>, recovery_set: TokenSet) { pub(super) fn pattern_top_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
let m = p.start(); pattern_r(p, recovery_set);
let has_leading_pipe = p.eat(T![|]);
pattern_r(p, m, has_leading_pipe, recovery_set);
} }
// test or_pattern // test or_pattern
@ -53,7 +46,10 @@ pub(super) fn pattern_top_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
// } // }
/// Parses a pattern list separated by pipes `|`, with no leading `|`,using the /// Parses a pattern list separated by pipes `|`, with no leading `|`,using the
/// given `recovery_set`. /// given `recovery_set`.
fn pattern_r(p: &mut Parser<'_>, m: Marker, has_leading_pipe: bool, recovery_set: TokenSet) { fn pattern_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
let m = p.start();
let has_leading_pipe = p.eat(T![|]);
pattern_single_r(p, recovery_set); pattern_single_r(p, recovery_set);
if !p.at(T![|]) && !has_leading_pipe { if !p.at(T![|]) && !has_leading_pipe {
@ -319,6 +315,8 @@ fn record_pat_field(p: &mut Parser<'_>) {
IDENT | INT_NUMBER if p.nth(1) == T![:] => { IDENT | INT_NUMBER if p.nth(1) == T![:] => {
name_ref_or_index(p); name_ref_or_index(p);
p.bump(T![:]); p.bump(T![:]);
// test record_field_pat_leading_or
// fn foo() { let R { a: | 1 | 2 } = 0; }
pattern(p); pattern(p);
} }
// test_err record_pat_field_eq_recovery // test_err record_pat_field_eq_recovery
@ -438,7 +436,7 @@ fn tuple_pat(p: &mut Parser<'_>) -> CompletedMarker {
} }
has_rest |= p.at(T![..]); has_rest |= p.at(T![..]);
pattern_top(p); pattern(p);
if !p.at(T![')']) { if !p.at(T![')']) {
has_comma = true; has_comma = true;
p.expect(T![,]); p.expect(T![,]);
@ -465,7 +463,7 @@ fn slice_pat(p: &mut Parser<'_>) -> CompletedMarker {
fn pat_list(p: &mut Parser<'_>, ket: SyntaxKind) { fn pat_list(p: &mut Parser<'_>, ket: SyntaxKind) {
while !p.at(EOF) && !p.at(ket) { while !p.at(EOF) && !p.at(ket) {
pattern_top(p); pattern(p);
if !p.eat(T![,]) { if !p.eat(T![,]) {
if p.at_ts(PAT_TOP_FIRST) { if p.at_ts(PAT_TOP_FIRST) {
p.error(format!("expected {:?}, got {:?}", T![,], p.current())); p.error(format!("expected {:?}, got {:?}", T![,], p.current()));

View File

@ -493,6 +493,10 @@ fn record_field_list() {
run_and_expect_no_errors("test_data/parser/inline/ok/record_field_list.rs"); run_and_expect_no_errors("test_data/parser/inline/ok/record_field_list.rs");
} }
#[test] #[test]
fn record_field_pat_leading_or() {
run_and_expect_no_errors("test_data/parser/inline/ok/record_field_pat_leading_or.rs");
}
#[test]
fn record_lit() { run_and_expect_no_errors("test_data/parser/inline/ok/record_lit.rs"); } fn record_lit() { run_and_expect_no_errors("test_data/parser/inline/ok/record_lit.rs"); }
#[test] #[test]
fn record_literal_field_with_attr() { fn record_literal_field_with_attr() {

View File

@ -0,0 +1,54 @@
SOURCE_FILE
FN
FN_KW "fn"
WHITESPACE " "
NAME
IDENT "foo"
PARAM_LIST
L_PAREN "("
R_PAREN ")"
WHITESPACE " "
BLOCK_EXPR
STMT_LIST
L_CURLY "{"
WHITESPACE " "
LET_STMT
LET_KW "let"
WHITESPACE " "
RECORD_PAT
PATH
PATH_SEGMENT
NAME_REF
IDENT "R"
WHITESPACE " "
RECORD_PAT_FIELD_LIST
L_CURLY "{"
WHITESPACE " "
RECORD_PAT_FIELD
NAME_REF
IDENT "a"
COLON ":"
WHITESPACE " "
OR_PAT
PIPE "|"
WHITESPACE " "
LITERAL_PAT
LITERAL
INT_NUMBER "1"
WHITESPACE " "
PIPE "|"
WHITESPACE " "
LITERAL_PAT
LITERAL
INT_NUMBER "2"
WHITESPACE " "
R_CURLY "}"
WHITESPACE " "
EQ "="
WHITESPACE " "
LITERAL
INT_NUMBER "0"
SEMICOLON ";"
WHITESPACE " "
R_CURLY "}"
WHITESPACE "\n"

View File

@ -0,0 +1 @@
fn foo() { let R { a: | 1 | 2 } = 0; }