Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #14580 - lowr:patch/parse-more-unstable-pat, r=Veykril
Parse more exclusive range patterns and inline const patterns Closes #13955 This PR - implements exclusive range pattern without start bound (tracking issue: rust-lang/rust#37854) - additionally moves rest pattern handling into the same place since they only differ in whether another pattern follows; this actually solves some FIXMEs - updates `PATTERN_FIRST` token set to include `const` token so we can parse inline const pattern in nested patterns
bors 2023-04-16
parent b218009 · parent 83a93f4 · commit c28f538
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mbe/matching.rs3
-rw-r--r--crates/parser/src/grammar/patterns.rs93
-rw-r--r--crates/parser/src/tests/prefix_entries.rs3
-rw-r--r--crates/parser/test_data/parser/inline/ok/0156_const_block_pat.rast120
-rw-r--r--crates/parser/test_data/parser/inline/ok/0156_const_block_pat.rs8
-rw-r--r--crates/parser/test_data/parser/inline/ok/0207_exclusive_range_pat.rast58
-rw-r--r--crates/parser/test_data/parser/inline/ok/0207_exclusive_range_pat.rs6
7 files changed, 253 insertions, 38 deletions
diff --git a/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs b/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
index 26f16542cb..e5cb9b9567 100644
--- a/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mbe/matching.rs
@@ -106,7 +106,6 @@ stringify!(;
#[test]
fn range_patterns() {
- // FIXME: rustc thinks there are three patterns here, not one.
check(
r#"
macro_rules! m {
@@ -118,7 +117,7 @@ m!(.. .. ..);
macro_rules! m {
($($p:pat)*) => (stringify!($($p |)*);)
}
-stringify!(.. .. .. |);
+stringify!(.. | .. | .. |);
"#]],
);
}
diff --git a/crates/parser/src/grammar/patterns.rs b/crates/parser/src/grammar/patterns.rs
index 5f4977886f..4801732101 100644
--- a/crates/parser/src/grammar/patterns.rs
+++ b/crates/parser/src/grammar/patterns.rs
@@ -5,6 +5,7 @@ pub(super) const PATTERN_FIRST: TokenSet =
T![box],
T![ref],
T![mut],
+ T![const],
T!['('],
T!['['],
T![&],
@@ -15,6 +16,10 @@ pub(super) const PATTERN_FIRST: TokenSet =
const PAT_TOP_FIRST: TokenSet = PATTERN_FIRST.union(TokenSet::new(&[T![|]]));
+/// Set of possible tokens at the start of a range pattern's end bound.
+const RANGE_PAT_END_FIRST: TokenSet =
+ expressions::LITERAL_FIRST.union(paths::PATH_FIRST).union(TokenSet::new(&[T![-], T![const]]));
+
pub(crate) fn pattern(p: &mut Parser<'_>) {
pattern_r(p, PAT_RECOVERY_SET);
}
@@ -105,6 +110,52 @@ fn pattern_single_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
return;
}
+ // test exclusive_range_pat
+ // fn main() {
+ // match 42 {
+ // ..0 => {}
+ // 1..2 => {}
+ // }
+ // }
+
+ // test dot_dot_pat
+ // fn main() {
+ // let .. = ();
+ // //
+ // // Tuples
+ // //
+ // let (a, ..) = ();
+ // let (a, ..,) = ();
+ // let Tuple(a, ..) = ();
+ // let Tuple(a, ..,) = ();
+ // let (.., ..) = ();
+ // let Tuple(.., ..) = ();
+ // let (.., a, ..) = ();
+ // let Tuple(.., a, ..) = ();
+ // //
+ // // Slices
+ // //
+ // let [..] = ();
+ // let [head, ..] = ();
+ // let [head, tail @ ..] = ();
+ // let [head, .., cons] = ();
+ // let [head, mid @ .., cons] = ();
+ // let [head, .., .., cons] = ();
+ // let [head, .., mid, tail @ ..] = ();
+ // let [head, .., mid, .., cons] = ();
+ // }
+ if p.at(T![..]) {
+ let m = p.start();
+ p.bump(T![..]);
+ if p.at_ts(RANGE_PAT_END_FIRST) {
+ atom_pat(p, recovery_set);
+ m.complete(p, RANGE_PAT);
+ } else {
+ m.complete(p, REST_PAT);
+ }
+ return;
+ }
+
if let Some(lhs) = atom_pat(p, recovery_set) {
for range_op in [T![...], T![..=], T![..]] {
if p.at(range_op) {
@@ -173,7 +224,6 @@ fn atom_pat(p: &mut Parser<'_>, recovery_set: TokenSet) -> Option<CompletedMarke
_ if paths::is_path_start(p) => path_or_macro_pat(p),
_ if is_literal_pat_start(p) => literal_pat(p),
- T![.] if p.at(T![..]) => rest_pat(p),
T![_] => wildcard_pat(p),
T![&] => ref_pat(p),
T!['('] => tuple_pat(p),
@@ -334,39 +384,6 @@ fn wildcard_pat(p: &mut Parser<'_>) -> CompletedMarker {
m.complete(p, WILDCARD_PAT)
}
-// test dot_dot_pat
-// fn main() {
-// let .. = ();
-// //
-// // Tuples
-// //
-// let (a, ..) = ();
-// let (a, ..,) = ();
-// let Tuple(a, ..) = ();
-// let Tuple(a, ..,) = ();
-// let (.., ..) = ();
-// let Tuple(.., ..) = ();
-// let (.., a, ..) = ();
-// let Tuple(.., a, ..) = ();
-// //
-// // Slices
-// //
-// let [..] = ();
-// let [head, ..] = ();
-// let [head, tail @ ..] = ();
-// let [head, .., cons] = ();
-// let [head, mid @ .., cons] = ();
-// let [head, .., .., cons] = ();
-// let [head, .., mid, tail @ ..] = ();
-// let [head, .., mid, .., cons] = ();
-// }
-fn rest_pat(p: &mut Parser<'_>) -> CompletedMarker {
- assert!(p.at(T![..]));
- let m = p.start();
- p.bump(T![..]);
- m.complete(p, REST_PAT)
-}
-
// test ref_pat
// fn main() {
// let &a = ();
@@ -483,6 +500,14 @@ fn box_pat(p: &mut Parser<'_>) -> CompletedMarker {
// fn main() {
// let const { 15 } = ();
// let const { foo(); bar() } = ();
+//
+// match 42 {
+// const { 0 } .. const { 1 } => (),
+// .. const { 0 } => (),
+// const { 2 } .. => (),
+// }
+//
+// let (const { () },) = ();
// }
fn const_block_pat(p: &mut Parser<'_>) -> CompletedMarker {
assert!(p.at(T![const]));
diff --git a/crates/parser/src/tests/prefix_entries.rs b/crates/parser/src/tests/prefix_entries.rs
index 40f92e5880..11f9c34abd 100644
--- a/crates/parser/src/tests/prefix_entries.rs
+++ b/crates/parser/src/tests/prefix_entries.rs
@@ -33,8 +33,7 @@ fn stmt() {
fn pat() {
check(PrefixEntryPoint::Pat, "x y", "x");
check(PrefixEntryPoint::Pat, "fn f() {}", "fn");
- // FIXME: This one is wrong, we should consume only one pattern.
- check(PrefixEntryPoint::Pat, ".. ..", ".. ..");
+ check(PrefixEntryPoint::Pat, ".. ..", "..");
}
#[test]
diff --git a/crates/parser/test_data/parser/inline/ok/0156_const_block_pat.rast b/crates/parser/test_data/parser/inline/ok/0156_const_block_pat.rast
index 59de2b9f16..593867a7b1 100644
--- a/crates/parser/test_data/parser/inline/ok/0156_const_block_pat.rast
+++ b/crates/parser/test_data/parser/inline/ok/0156_const_block_pat.rast
@@ -74,6 +74,126 @@ SOURCE_FILE
L_PAREN "("
R_PAREN ")"
SEMICOLON ";"
+ WHITESPACE "\n\n "
+ EXPR_STMT
+ MATCH_EXPR
+ MATCH_KW "match"
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "42"
+ WHITESPACE " "
+ MATCH_ARM_LIST
+ L_CURLY "{"
+ WHITESPACE "\n "
+ MATCH_ARM
+ RANGE_PAT
+ CONST_BLOCK_PAT
+ CONST_KW "const"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "0"
+ WHITESPACE " "
+ R_CURLY "}"
+ WHITESPACE " "
+ DOT2 ".."
+ WHITESPACE " "
+ CONST_BLOCK_PAT
+ CONST_KW "const"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "1"
+ WHITESPACE " "
+ R_CURLY "}"
+ WHITESPACE " "
+ FAT_ARROW "=>"
+ WHITESPACE " "
+ TUPLE_EXPR
+ L_PAREN "("
+ R_PAREN ")"
+ COMMA ","
+ WHITESPACE "\n "
+ MATCH_ARM
+ RANGE_PAT
+ DOT2 ".."
+ WHITESPACE " "
+ CONST_BLOCK_PAT
+ CONST_KW "const"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "0"
+ WHITESPACE " "
+ R_CURLY "}"
+ WHITESPACE " "
+ FAT_ARROW "=>"
+ WHITESPACE " "
+ TUPLE_EXPR
+ L_PAREN "("
+ R_PAREN ")"
+ COMMA ","
+ WHITESPACE "\n "
+ MATCH_ARM
+ RANGE_PAT
+ CONST_BLOCK_PAT
+ CONST_KW "const"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "2"
+ WHITESPACE " "
+ R_CURLY "}"
+ WHITESPACE " "
+ DOT2 ".."
+ WHITESPACE " "
+ FAT_ARROW "=>"
+ WHITESPACE " "
+ TUPLE_EXPR
+ L_PAREN "("
+ R_PAREN ")"
+ COMMA ","
+ WHITESPACE "\n "
+ R_CURLY "}"
+ WHITESPACE "\n\n "
+ LET_STMT
+ LET_KW "let"
+ WHITESPACE " "
+ TUPLE_PAT
+ L_PAREN "("
+ CONST_BLOCK_PAT
+ CONST_KW "const"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE " "
+ TUPLE_EXPR
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE " "
+ R_CURLY "}"
+ COMMA ","
+ R_PAREN ")"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ TUPLE_EXPR
+ L_PAREN "("
+ R_PAREN ")"
+ SEMICOLON ";"
WHITESPACE "\n"
R_CURLY "}"
WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/inline/ok/0156_const_block_pat.rs b/crates/parser/test_data/parser/inline/ok/0156_const_block_pat.rs
index dce9defac2..6ecdee849b 100644
--- a/crates/parser/test_data/parser/inline/ok/0156_const_block_pat.rs
+++ b/crates/parser/test_data/parser/inline/ok/0156_const_block_pat.rs
@@ -1,4 +1,12 @@
fn main() {
let const { 15 } = ();
let const { foo(); bar() } = ();
+
+ match 42 {
+ const { 0 } .. const { 1 } => (),
+ .. const { 0 } => (),
+ const { 2 } .. => (),
+ }
+
+ let (const { () },) = ();
}
diff --git a/crates/parser/test_data/parser/inline/ok/0207_exclusive_range_pat.rast b/crates/parser/test_data/parser/inline/ok/0207_exclusive_range_pat.rast
new file mode 100644
index 0000000000..fd2c422d0d
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0207_exclusive_range_pat.rast
@@ -0,0 +1,58 @@
+SOURCE_FILE
+ FN
+ FN_KW "fn"
+ WHITESPACE " "
+ NAME
+ IDENT "main"
+ PARAM_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE "\n "
+ MATCH_EXPR
+ MATCH_KW "match"
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "42"
+ WHITESPACE " "
+ MATCH_ARM_LIST
+ L_CURLY "{"
+ WHITESPACE "\n "
+ MATCH_ARM
+ RANGE_PAT
+ DOT2 ".."
+ LITERAL_PAT
+ LITERAL
+ INT_NUMBER "0"
+ WHITESPACE " "
+ FAT_ARROW "=>"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ R_CURLY "}"
+ WHITESPACE "\n "
+ MATCH_ARM
+ RANGE_PAT
+ LITERAL_PAT
+ LITERAL
+ INT_NUMBER "1"
+ DOT2 ".."
+ LITERAL_PAT
+ LITERAL
+ INT_NUMBER "2"
+ WHITESPACE " "
+ FAT_ARROW "=>"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ R_CURLY "}"
+ WHITESPACE "\n "
+ R_CURLY "}"
+ WHITESPACE "\n"
+ R_CURLY "}"
+ WHITESPACE "\n"
diff --git a/crates/parser/test_data/parser/inline/ok/0207_exclusive_range_pat.rs b/crates/parser/test_data/parser/inline/ok/0207_exclusive_range_pat.rs
new file mode 100644
index 0000000000..e80505d8bd
--- /dev/null
+++ b/crates/parser/test_data/parser/inline/ok/0207_exclusive_range_pat.rs
@@ -0,0 +1,6 @@
+fn main() {
+ match 42 {
+ ..0 => {}
+ 1..2 => {}
+ }
+}