From fc8834fa2ec3a46055629528ad85d4c0a53e78cb Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 21 Apr 2021 15:44:41 -0700 Subject: [PATCH] Allow struct and enum to contain inner attrs --- compiler/rustc_parse/src/parser/item.rs | 60 +++++++++++++++++-------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 93f5d79c0db13..2cab91a31e25f 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1,6 +1,6 @@ use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error}; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; -use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken}; +use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, SeqSep, TrailingToken}; use rustc_ast::ast::*; use rustc_ast::ptr::P; @@ -272,14 +272,14 @@ impl<'a> Parser<'a> { self.parse_type_alias(def())? } else if self.eat_keyword(kw::Enum) { // ENUM ITEM - self.parse_item_enum()? + self.parse_item_enum(attrs)? } else if self.eat_keyword(kw::Struct) { // STRUCT ITEM - self.parse_item_struct()? + self.parse_item_struct(attrs)? } else if self.is_kw_followed_by_ident(kw::Union) { // UNION ITEM self.bump(); // `union` - self.parse_item_union()? + self.parse_item_union(attrs)? } else if self.eat_keyword(kw::Macro) { // MACROS 2.0 ITEM self.parse_item_decl_macro(lo)? @@ -1190,13 +1190,20 @@ impl<'a> Parser<'a> { } /// Parses an enum declaration. - fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> { + fn parse_item_enum(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { let id = self.parse_ident()?; let mut generics = self.parse_generics()?; generics.where_clause = self.parse_where_clause()?; - let (variants, _) = - self.parse_delim_comma_seq(token::Brace, |p| p.parse_enum_variant()).map_err(|e| { + self.expect(&token::OpenDelim(token::Brace))?; + attrs.append(&mut self.parse_inner_attributes()?); + let (variants, _) = self + .parse_seq_to_end( + &token::CloseDelim(token::Brace), + SeqSep::trailing_allowed(token::Comma), + |p| p.parse_enum_variant(), + ) + .map_err(|e| { self.recover_stmt(); e })?; @@ -1210,7 +1217,7 @@ impl<'a> Parser<'a> { self.collect_tokens_trailing_token( variant_attrs, ForceCollect::No, - |this, variant_attrs| { + |this, mut variant_attrs| { let vlo = this.token.span; let vis = this.parse_visibility(FollowedByType::No)?; @@ -1221,7 +1228,8 @@ impl<'a> Parser<'a> { let struct_def = if this.check(&token::OpenDelim(token::Brace)) { // Parse a struct variant. - let (fields, recovered) = this.parse_record_struct_body("struct", false)?; + let (fields, recovered) = + this.parse_record_struct_body("struct", false, &mut variant_attrs)?; VariantData::Struct(fields, recovered) } else if this.check(&token::OpenDelim(token::Paren)) { VariantData::Tuple(this.parse_tuple_struct_body()?, DUMMY_NODE_ID) @@ -1249,7 +1257,7 @@ impl<'a> Parser<'a> { } /// Parses `struct Foo { ... }`. - fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> { + fn parse_item_struct(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { let class_name = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -1275,8 +1283,11 @@ impl<'a> Parser<'a> { VariantData::Unit(DUMMY_NODE_ID) } else { // If we see: `struct Foo where T: Copy { ... }` - let (fields, recovered) = - self.parse_record_struct_body("struct", generics.where_clause.has_where_token)?; + let (fields, recovered) = self.parse_record_struct_body( + "struct", + generics.where_clause.has_where_token, + attrs, + )?; VariantData::Struct(fields, recovered) } // No `where` so: `struct Foo;` @@ -1284,8 +1295,11 @@ impl<'a> Parser<'a> { VariantData::Unit(DUMMY_NODE_ID) // Record-style struct definition } else if self.token == token::OpenDelim(token::Brace) { - let (fields, recovered) = - self.parse_record_struct_body("struct", generics.where_clause.has_where_token)?; + let (fields, recovered) = self.parse_record_struct_body( + "struct", + generics.where_clause.has_where_token, + attrs, + )?; VariantData::Struct(fields, recovered) // Tuple-style struct definition with optional where-clause. } else if self.token == token::OpenDelim(token::Paren) { @@ -1308,19 +1322,25 @@ impl<'a> Parser<'a> { } /// Parses `union Foo { ... }`. - fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> { + fn parse_item_union(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { let class_name = self.parse_ident()?; let mut generics = self.parse_generics()?; let vdata = if self.token.is_keyword(kw::Where) { generics.where_clause = self.parse_where_clause()?; - let (fields, recovered) = - self.parse_record_struct_body("union", generics.where_clause.has_where_token)?; + let (fields, recovered) = self.parse_record_struct_body( + "union", + generics.where_clause.has_where_token, + attrs, + )?; VariantData::Struct(fields, recovered) } else if self.token == token::OpenDelim(token::Brace) { - let (fields, recovered) = - self.parse_record_struct_body("union", generics.where_clause.has_where_token)?; + let (fields, recovered) = self.parse_record_struct_body( + "union", + generics.where_clause.has_where_token, + attrs, + )?; VariantData::Struct(fields, recovered) } else { let token_str = super::token_descr(&self.token); @@ -1337,10 +1357,12 @@ impl<'a> Parser<'a> { &mut self, adt_ty: &str, parsed_where: bool, + attrs: &mut Vec, ) -> PResult<'a, (Vec, /* recovered */ bool)> { let mut fields = Vec::new(); let mut recovered = false; if self.eat(&token::OpenDelim(token::Brace)) { + attrs.append(&mut self.parse_inner_attributes()?); while self.token != token::CloseDelim(token::Brace) { let field = self.parse_field_def(adt_ty).map_err(|e| { self.consume_block(token::Brace, ConsumeClosingDelim::No);