From 0c3ff6c8fc3b4fda0a1b2333f15e3d69ae4a6de4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 18 Sep 2022 15:44:54 -0700 Subject: [PATCH] Parse Struct { #[attr] .. } in pattern position --- src/pat.rs | 35 +++++++++++++++++++---------------- tests/repo/mod.rs | 3 --- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/pat.rs b/src/pat.rs index fa0818c16a..b279186aa0 100644 --- a/src/pat.rs +++ b/src/pat.rs @@ -400,11 +400,11 @@ pub mod parsing { } if input.peek(token::Brace) { - let pat = pat_struct(input, path)?; + let pat = pat_struct(begin.fork(), input, path)?; if qself.is_some() { Ok(Pat::Verbatim(verbatim::between(begin, input))) } else { - Ok(Pat::Struct(pat)) + Ok(pat) } } else if input.peek(token::Paren) { let pat = pat_tuple_struct(input, path)?; @@ -465,13 +465,23 @@ pub mod parsing { }) } - fn pat_struct(input: ParseStream, path: Path) -> Result { + fn pat_struct(begin: ParseBuffer, input: ParseStream, path: Path) -> Result { let content; let brace_token = braced!(content in input); let mut fields = Punctuated::new(); - while !content.is_empty() && !content.peek(Token![..]) { - let value = content.call(field_pat)?; + let mut dot2_token = None; + while !content.is_empty() { + let attrs = content.call(Attribute::parse_outer)?; + if content.peek(Token![..]) { + dot2_token = Some(content.parse()?); + if !attrs.is_empty() { + return Ok(Pat::Verbatim(verbatim::between(begin, input))); + } + break; + } + let mut value = content.call(field_pat)?; + value.attrs = attrs; fields.push_value(value); if content.is_empty() { break; @@ -480,19 +490,13 @@ pub mod parsing { fields.push_punct(punct); } - let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) { - Some(content.parse()?) - } else { - None - }; - - Ok(PatStruct { + Ok(Pat::Struct(PatStruct { attrs: Vec::new(), path, brace_token, fields, dot2_token, - }) + })) } impl Member { @@ -505,7 +509,6 @@ pub mod parsing { } fn field_pat(input: ParseStream) -> Result { - let attrs = input.call(Attribute::parse_outer)?; let boxed: Option = input.parse()?; let by_ref: Option = input.parse()?; let mutability: Option = input.parse()?; @@ -515,7 +518,7 @@ pub mod parsing { || member.is_unnamed() { return Ok(FieldPat { - attrs, + attrs: Vec::new(), member, colon_token: input.parse()?, pat: Box::new(multi_pat_with_leading_vert(input)?), @@ -544,7 +547,7 @@ pub mod parsing { } Ok(FieldPat { - attrs, + attrs: Vec::new(), member: Member::Named(ident), colon_token: None, pat: Box::new(pat), diff --git a/tests/repo/mod.rs b/tests/repo/mod.rs index 9d45f32711..b88f693757 100644 --- a/tests/repo/mod.rs +++ b/tests/repo/mod.rs @@ -14,9 +14,6 @@ const REVISION: &str = "98ad6a5519651af36e246c0335c964dd52c554ba"; #[rustfmt::skip] static EXCLUDE_FILES: &[&str] = &[ - // TODO: Struct { #[attr] .. } in pattern position - "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0102_record_pat_field_list.rs", - // TODO: static async closures, for<> move closures "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0106_lambda_expr.rs",