Unnamed repository; edit this file 'description' to name the repository.
Parse outer attributes on StructPatternEtCetera
6 files changed, 103 insertions, 32 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 804d98ce38..bafaa72661 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs @@ -821,7 +821,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 81e2051abb..7ba81d0cb1 100644 --- a/crates/parser/src/grammar/patterns.rs +++ b/crates/parser/src/grammar/patterns.rs @@ -200,12 +200,43 @@ 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!['{'])); @@ -214,32 +245,26 @@ fn record_pat_field_list(p: &mut Parser) { while !p.at(EOF) && !p.at(T!['}']) { match p.current() { // A trailing `..` is *not* treated as a REST_PAT. - T![.] if p.at(T![..]) => p.bump(T![..]), + T![.] if p.at(T![..]) => { + rest_pat(p); + } T!['{'] => error_block(p, "expected ident"), + T![#] => { + let m = p.start(); + attributes::outer_attrs(p); + if p.at(T![..]) { + p.bump(T![..]); + m.complete(p, REST_PAT); + } else { + record_pat_field(p); + m.complete(p, RECORD_PAT_FIELD); + } + } _ => { 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/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index 5d92a0f9e5..9d4aad2d2b 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -1175,6 +1175,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![..]) } } @@ -1289,7 +1290,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!['}']) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -3687,6 +3688,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] - [email protected] ".." + [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 @@ [email protected] "fn" @@ -8,8 +8,8 @@ [email protected] [email protected] "\n " @@ -89,7 +89,8 @@ [email protected] - [email protected] ".." + [email protected] ".." @@ -128,6 +129,47 @@ [email protected] - [email protected] "\n" - [email protected] "}" - [email protected] "\n" + [email protected] "\n " + [email protected] "let" + [email protected] " " + [email protected] "S" + [email protected] " " + [email protected] "{" + [email protected] " " + [email protected] "#" + [email protected] "[" + [email protected] "cfg" + [email protected] "(" + [email protected] "any" + [email protected] "(" + [email protected] ")" + [email protected] ")" + [email protected] "]" + [email protected] " " + [email protected] ".." + [email protected] " " + [email protected] "}" + [email protected] " " + [email protected] "=" + [email protected] " " + [email protected] "(" + [email protected] ")" + [email protected] ";" + [email protected] "\n" + [email protected] "}" + [email protected] "\n" 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())] .. } = (); } |