Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir_def/src/body/lower.rs2
-rw-r--r--crates/parser/src/grammar/patterns.rs68
-rw-r--r--crates/syntax/Cargo.toml2
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs4
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0008_path_part.rast3
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0102_record_pat_field_list.rast58
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0102_record_pat_field_list.rs1
7 files changed, 101 insertions, 37 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 4c1a3344ec..372cf9aba8 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -818,7 +818,7 @@ impl ExprCollector<'_> {
let ellipsis = p
.record_pat_field_list()
.expect("every struct should have a field list")
- .dotdot_token()
+ .rest_pat()
.is_some();
Pat::Record { path, args, ellipsis }
diff --git a/crates/parser/src/grammar/patterns.rs b/crates/parser/src/grammar/patterns.rs
index 5fe1a7b13b..9da94ce162 100644
--- a/crates/parser/src/grammar/patterns.rs
+++ b/crates/parser/src/grammar/patterns.rs
@@ -205,46 +205,64 @@ fn tuple_pat_fields(p: &mut Parser) {
p.expect(T![')']);
}
+// test record_pat_field
+// fn foo() {
+// let S { 0: 1 } = ();
+// let S { x: 1 } = ();
+// let S { #[cfg(any())] x: 1 } = ();
+// }
+fn record_pat_field(p: &mut Parser) {
+ match p.current() {
+ IDENT | INT_NUMBER if p.nth(1) == T![:] => {
+ name_ref_or_index(p);
+ p.bump(T![:]);
+ pattern(p);
+ }
+ T![.] => {
+ if p.at(T![..]) {
+ p.bump(T![..]);
+ } else {
+ ident_pat(p, false);
+ }
+ }
+ T![box] => {
+ // FIXME: not all box patterns should be allowed
+ box_pat(p);
+ }
+ _ => {
+ ident_pat(p, false);
+ }
+ }
+}
+
// test record_pat_field_list
// fn foo() {
// let S {} = ();
// let S { f, ref mut g } = ();
// let S { h: _, ..} = ();
// let S { h: _, } = ();
+// let S { #[cfg(any())] .. } = ();
// }
fn record_pat_field_list(p: &mut Parser) {
assert!(p.at(T!['{']));
let m = p.start();
p.bump(T!['{']);
while !p.at(EOF) && !p.at(T!['}']) {
+ let m = p.start();
+ attributes::outer_attrs(p);
+
match p.current() {
// A trailing `..` is *not* treated as a REST_PAT.
- T![.] if p.at(T![..]) => p.bump(T![..]),
- T!['{'] => error_block(p, "expected ident"),
-
+ T![.] if p.at(T![..]) => {
+ p.bump(T![..]);
+ m.complete(p, REST_PAT);
+ }
+ T!['{'] => {
+ error_block(p, "expected ident");
+ m.abandon(p);
+ }
_ => {
- let m = p.start();
- attributes::outer_attrs(p);
- match p.current() {
- // test record_pat_field
- // fn foo() {
- // let S { 0: 1 } = ();
- // let S { x: 1 } = ();
- // let S { #[cfg(any())] x: 1 } = ();
- // }
- IDENT | INT_NUMBER if p.nth(1) == T![:] => {
- name_ref_or_index(p);
- p.bump(T![:]);
- pattern(p);
- }
- T![box] => {
- // FIXME: not all box patterns should be allowed
- box_pat(p);
- }
- _ => {
- ident_pat(p, false);
- }
- }
+ record_pat_field(p);
m.complete(p, RECORD_PAT_FIELD);
}
}
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index f889fa2a2c..3c5adb97fb 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -29,7 +29,7 @@ rayon = "1"
expect-test = "1.1"
proc-macro2 = "1.0.8"
quote = "1.0.2"
-ungrammar = "=1.14.5"
+ungrammar = "=1.14.6"
test_utils = { path = "../test_utils" }
sourcegen = { path = "../sourcegen" }
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 1810033e84..f69c873663 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -1290,6 +1290,7 @@ impl BoxPat {
pub struct RestPat {
pub(crate) syntax: SyntaxNode,
}
+impl ast::HasAttrs for RestPat {}
impl RestPat {
pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
}
@@ -1418,7 +1419,7 @@ pub struct RecordPatFieldList {
impl RecordPatFieldList {
pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
pub fn fields(&self) -> AstChildren<RecordPatField> { support::children(&self.syntax) }
- pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
+ pub fn rest_pat(&self) -> Option<RestPat> { support::child(&self.syntax) }
pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
}
@@ -3836,6 +3837,7 @@ impl AstNode for AnyHasAttrs {
| MATCH_ARM_LIST
| MATCH_ARM
| IDENT_PAT
+ | REST_PAT
| RECORD_PAT_FIELD => true,
_ => false,
}
diff --git a/crates/syntax/test_data/parser/inline/ok/0008_path_part.rast b/crates/syntax/test_data/parser/inline/ok/0008_path_part.rast
index ff81307128..c20e41ffae 100644
--- a/crates/syntax/test_data/parser/inline/ok/0008_path_part.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0008_path_part.rast
@@ -62,7 +62,8 @@ [email protected]
diff --git a/crates/syntax/test_data/parser/inline/ok/0102_record_pat_field_list.rast b/crates/syntax/test_data/parser/inline/ok/0102_record_pat_field_list.rast
index 4c44da9d55..761438d2ec 100644
--- a/crates/syntax/test_data/parser/inline/ok/0102_record_pat_field_list.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0102_record_pat_field_list.rast
@@ -1,5 +1,5 @@
@@ -8,8 +8,8 @@ [email protected]
@@ -89,7 +89,8 @@ [email protected]
@@ -128,6 +129,47 @@ [email protected]
diff --git a/crates/syntax/test_data/parser/inline/ok/0102_record_pat_field_list.rs b/crates/syntax/test_data/parser/inline/ok/0102_record_pat_field_list.rs
index da3412fa8a..0bfaae7c4d 100644
--- a/crates/syntax/test_data/parser/inline/ok/0102_record_pat_field_list.rs
+++ b/crates/syntax/test_data/parser/inline/ok/0102_record_pat_field_list.rs
@@ -3,4 +3,5 @@ fn foo() {
let S { f, ref mut g } = ();
let S { h: _, ..} = ();
let S { h: _, } = ();
+ let S { #[cfg(any())] .. } = ();
}