Skip to content

Commit 94fa49c

Browse files
bors[bot]xffxff
andauthored
Merge #10420
10420: Parse outer attributes on StructPatternEtCetera r=jonas-schievink a=XFFXFF Try to fix #8610 Related pr in ungrammer: rust-analyzer/ungrammar#41 Co-authored-by: zhoufan <[email protected]>
2 parents 4cfe237 + 116c7ae commit 94fa49c

File tree

7 files changed

+101
-37
lines changed

7 files changed

+101
-37
lines changed

crates/hir_def/src/body/lower.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ impl ExprCollector<'_> {
818818
let ellipsis = p
819819
.record_pat_field_list()
820820
.expect("every struct should have a field list")
821-
.dotdot_token()
821+
.rest_pat()
822822
.is_some();
823823

824824
Pat::Record { path, args, ellipsis }

crates/parser/src/grammar/patterns.rs

+43-25
Original file line numberDiff line numberDiff line change
@@ -205,46 +205,64 @@ fn tuple_pat_fields(p: &mut Parser) {
205205
p.expect(T![')']);
206206
}
207207

208+
// test record_pat_field
209+
// fn foo() {
210+
// let S { 0: 1 } = ();
211+
// let S { x: 1 } = ();
212+
// let S { #[cfg(any())] x: 1 } = ();
213+
// }
214+
fn record_pat_field(p: &mut Parser) {
215+
match p.current() {
216+
IDENT | INT_NUMBER if p.nth(1) == T![:] => {
217+
name_ref_or_index(p);
218+
p.bump(T![:]);
219+
pattern(p);
220+
}
221+
T![.] => {
222+
if p.at(T![..]) {
223+
p.bump(T![..]);
224+
} else {
225+
ident_pat(p, false);
226+
}
227+
}
228+
T![box] => {
229+
// FIXME: not all box patterns should be allowed
230+
box_pat(p);
231+
}
232+
_ => {
233+
ident_pat(p, false);
234+
}
235+
}
236+
}
237+
208238
// test record_pat_field_list
209239
// fn foo() {
210240
// let S {} = ();
211241
// let S { f, ref mut g } = ();
212242
// let S { h: _, ..} = ();
213243
// let S { h: _, } = ();
244+
// let S { #[cfg(any())] .. } = ();
214245
// }
215246
fn record_pat_field_list(p: &mut Parser) {
216247
assert!(p.at(T!['{']));
217248
let m = p.start();
218249
p.bump(T!['{']);
219250
while !p.at(EOF) && !p.at(T!['}']) {
251+
let m = p.start();
252+
attributes::outer_attrs(p);
253+
220254
match p.current() {
221255
// A trailing `..` is *not* treated as a REST_PAT.
222-
T![.] if p.at(T![..]) => p.bump(T![..]),
223-
T!['{'] => error_block(p, "expected ident"),
224-
256+
T![.] if p.at(T![..]) => {
257+
p.bump(T![..]);
258+
m.complete(p, REST_PAT);
259+
}
260+
T!['{'] => {
261+
error_block(p, "expected ident");
262+
m.abandon(p);
263+
}
225264
_ => {
226-
let m = p.start();
227-
attributes::outer_attrs(p);
228-
match p.current() {
229-
// test record_pat_field
230-
// fn foo() {
231-
// let S { 0: 1 } = ();
232-
// let S { x: 1 } = ();
233-
// let S { #[cfg(any())] x: 1 } = ();
234-
// }
235-
IDENT | INT_NUMBER if p.nth(1) == T![:] => {
236-
name_ref_or_index(p);
237-
p.bump(T![:]);
238-
pattern(p);
239-
}
240-
T![box] => {
241-
// FIXME: not all box patterns should be allowed
242-
box_pat(p);
243-
}
244-
_ => {
245-
ident_pat(p, false);
246-
}
247-
}
265+
record_pat_field(p);
248266
m.complete(p, RECORD_PAT_FIELD);
249267
}
250268
}

crates/syntax/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ rayon = "1"
2929
expect-test = "1.1"
3030
proc-macro2 = "1.0.8"
3131
quote = "1.0.2"
32-
ungrammar = "=1.14.5"
32+
ungrammar = "=1.14.6"
3333

3434
test_utils = { path = "../test_utils" }
3535
sourcegen = { path = "../sourcegen" }

crates/syntax/src/ast/generated/nodes.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1290,6 +1290,7 @@ impl BoxPat {
12901290
pub struct RestPat {
12911291
pub(crate) syntax: SyntaxNode,
12921292
}
1293+
impl ast::HasAttrs for RestPat {}
12931294
impl RestPat {
12941295
pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
12951296
}
@@ -1418,7 +1419,7 @@ pub struct RecordPatFieldList {
14181419
impl RecordPatFieldList {
14191420
pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
14201421
pub fn fields(&self) -> AstChildren<RecordPatField> { support::children(&self.syntax) }
1421-
pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
1422+
pub fn rest_pat(&self) -> Option<RestPat> { support::child(&self.syntax) }
14221423
pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
14231424
}
14241425

@@ -3836,6 +3837,7 @@ impl AstNode for AnyHasAttrs {
38363837
| MATCH_ARM_LIST
38373838
| MATCH_ARM
38383839
| IDENT_PAT
3840+
| REST_PAT
38393841
| RECORD_PAT_FIELD => true,
38403842
_ => false,
38413843
}

crates/syntax/test_data/parser/inline/ok/0008_path_part.rast

+2-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ [email protected]
6262
6363
6464
65-
65+
66+
6667
6768
6869

crates/syntax/test_data/parser/inline/ok/0102_record_pat_field_list.rast

+50-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
SOURCE_FILE@0..119
2-
FN@0..118
1+
SOURCE_FILE@0..156
2+
FN@0..155
33
44
55
@@ -8,8 +8,8 @@ [email protected]
88
99
1010
11-
BLOCK_EXPR@9..118
12-
STMT_LIST@9..118
11+
BLOCK_EXPR@9..155
12+
STMT_LIST@9..155
1313
1414
1515
@@ -89,7 +89,8 @@ [email protected]
8989
9090
9191
92-
92+
93+
9394
9495
9596
@@ -128,6 +129,47 @@ [email protected]
128129
129130
130131
131-
132-
133-
132+
133+
134+
135+
136+
137+
138+
139+
140+
141+
142+
143+
144+
145+
146+
147+
148+
149+
150+
151+
152+
153+
154+
155+
156+
157+
158+
159+
160+
161+
162+
163+
164+
165+
166+
167+
168+
169+
170+
171+
172+
173+
174+
175+

crates/syntax/test_data/parser/inline/ok/0102_record_pat_field_list.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ fn foo() {
33
let S { f, ref mut g } = ();
44
let S { h: _, ..} = ();
55
let S { h: _, } = ();
6+
let S { #[cfg(any())] .. } = ();
67
}

0 commit comments

Comments
 (0)