Auto merge of #13096 - jonas-schievink:parse-more-or-pats, r=jonas-schievink

fix: Allow leading `|` in more pattern positions

fixes https://github.com/rust-lang/rust-analyzer/issues/12894, fixes https://github.com/rust-lang/rust-analyzer/issues/13094

Oddly, the leading `|` token does not end up inside the `OR_PAT` node, since `pattern_top_r` consumes it first. This is a preexisting issue in match arms though, so I didn't fix it here.
This commit is contained in:
bors 2022-08-23 14:35:03 +00:00
commit e73b7a9ec7
7 changed files with 98 additions and 4 deletions

View file

@ -13,6 +13,8 @@ pub(super) const PATTERN_FIRST: TokenSet =
T![.],
]));
const PAT_TOP_FIRST: TokenSet = PATTERN_FIRST.union(TokenSet::new(&[T![|]]));
pub(crate) fn pattern(p: &mut Parser<'_>) {
pattern_r(p, PAT_RECOVERY_SET);
}
@ -228,6 +230,7 @@ fn path_or_macro_pat(p: &mut Parser<'_>) -> CompletedMarker {
// let S(_) = ();
// let S(_,) = ();
// let S(_, .. , x) = ();
// let S(| a) = ();
// }
fn tuple_pat_fields(p: &mut Parser<'_>) {
assert!(p.at(T!['(']));
@ -363,6 +366,7 @@ fn ref_pat(p: &mut Parser<'_>) -> CompletedMarker {
// let (a,) = ();
// let (..) = ();
// let () = ();
// let (| a | a, | b) = ((),());
// }
fn tuple_pat(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(T!['(']));
@ -373,13 +377,13 @@ fn tuple_pat(p: &mut Parser<'_>) -> CompletedMarker {
let mut has_rest = false;
while !p.at(EOF) && !p.at(T![')']) {
has_pat = true;
if !p.at_ts(PATTERN_FIRST) {
if !p.at_ts(PAT_TOP_FIRST) {
p.error("expected a pattern");
break;
}
has_rest |= p.at(T![..]);
pattern(p);
pattern_top(p);
if !p.at(T![')']) {
has_comma = true;
p.expect(T![,]);
@ -393,6 +397,7 @@ fn tuple_pat(p: &mut Parser<'_>) -> CompletedMarker {
// test slice_pat
// fn main() {
// let [a, b, ..] = [];
// let [| a, ..] = [];
// }
fn slice_pat(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(T!['[']));
@ -405,12 +410,12 @@ fn slice_pat(p: &mut Parser<'_>) -> CompletedMarker {
fn pat_list(p: &mut Parser<'_>, ket: SyntaxKind) {
while !p.at(EOF) && !p.at(ket) {
if !p.at_ts(PATTERN_FIRST) {
if !p.at_ts(PAT_TOP_FIRST) {
p.error("expected a pattern");
break;
}
pattern(p);
pattern_top(p);
if !p.at(ket) {
p.expect(T![,]);
}

View file

@ -37,6 +37,29 @@ SOURCE_FILE
L_BRACK "["
R_BRACK "]"
SEMICOLON ";"
WHITESPACE "\n "
LET_STMT
LET_KW "let"
WHITESPACE " "
SLICE_PAT
L_BRACK "["
PIPE "|"
WHITESPACE " "
IDENT_PAT
NAME
IDENT "a"
COMMA ","
WHITESPACE " "
REST_PAT
DOT2 ".."
R_BRACK "]"
WHITESPACE " "
EQ "="
WHITESPACE " "
ARRAY_EXPR
L_BRACK "["
R_BRACK "]"
SEMICOLON ";"
WHITESPACE "\n"
R_CURLY "}"
WHITESPACE "\n"

View file

@ -1,3 +1,4 @@
fn main() {
let [a, b, ..] = [];
let [| a, ..] = [];
}

View file

@ -100,6 +100,29 @@ SOURCE_FILE
L_PAREN "("
R_PAREN ")"
SEMICOLON ";"
WHITESPACE "\n "
LET_STMT
LET_KW "let"
WHITESPACE " "
TUPLE_STRUCT_PAT
PATH
PATH_SEGMENT
NAME_REF
IDENT "S"
L_PAREN "("
PIPE "|"
WHITESPACE " "
IDENT_PAT
NAME
IDENT "a"
R_PAREN ")"
WHITESPACE " "
EQ "="
WHITESPACE " "
TUPLE_EXPR
L_PAREN "("
R_PAREN ")"
SEMICOLON ";"
WHITESPACE "\n"
R_CURLY "}"
WHITESPACE "\n"

View file

@ -3,4 +3,5 @@ fn foo() {
let S(_) = ();
let S(_,) = ();
let S(_, .. , x) = ();
let S(| a) = ();
}

View file

@ -85,6 +85,46 @@ SOURCE_FILE
L_PAREN "("
R_PAREN ")"
SEMICOLON ";"
WHITESPACE "\n "
LET_STMT
LET_KW "let"
WHITESPACE " "
TUPLE_PAT
L_PAREN "("
PIPE "|"
WHITESPACE " "
OR_PAT
IDENT_PAT
NAME
IDENT "a"
WHITESPACE " "
PIPE "|"
WHITESPACE " "
IDENT_PAT
NAME
IDENT "a"
COMMA ","
WHITESPACE " "
PIPE "|"
WHITESPACE " "
IDENT_PAT
NAME
IDENT "b"
R_PAREN ")"
WHITESPACE " "
EQ "="
WHITESPACE " "
TUPLE_EXPR
L_PAREN "("
TUPLE_EXPR
L_PAREN "("
R_PAREN ")"
COMMA ","
TUPLE_EXPR
L_PAREN "("
R_PAREN ")"
R_PAREN ")"
SEMICOLON ";"
WHITESPACE "\n"
R_CURLY "}"
WHITESPACE "\n"

View file

@ -3,4 +3,5 @@ fn main() {
let (a,) = ();
let (..) = ();
let () = ();
let (| a | a, | b) = ((),());
}