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 26f16542cbb..e5cb9b95676 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 @@ macro_rules! m { #[test] fn range_patterns() { - // FIXME: rustc thinks there are three patterns here, not one. check( r#" macro_rules! m { @@ -118,7 +117,7 @@ macro_rules! 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 5f4977886f6..4801732101f 100644 --- a/crates/parser/src/grammar/patterns.rs +++ b/crates/parser/src/grammar/patterns.rs @@ -5,6 +5,7 @@ T![box], T![ref], T![mut], + T![const], T!['('], T!['['], T![&], @@ -15,6 +16,10 @@ 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 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 40f92e58804..11f9c34abdf 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 59de2b9f163..593867a7b12 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 dce9defac2f..6ecdee849b7 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 00000000000..fd2c422d0d1 --- /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 00000000000..e80505d8bd4 --- /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 => {} + } +}