Skip to content

Commit d668fab

Browse files
committed
Auto merge of #29714 - petrochenkov:strparse, r=nrc
In particular, attributes are now parsed on fields of tuple variants
2 parents ea422eb + 649fc38 commit d668fab

File tree

4 files changed

+51
-52
lines changed

4 files changed

+51
-52
lines changed

src/libsyntax/feature_gate.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,8 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
867867
self.context.span_handler.span_err(span, "empty tuple structs and enum variants \
868868
are not allowed, use unit structs and \
869869
enum variants instead");
870+
self.context.span_handler.span_help(span, "remove trailing `()` to make a unit \
871+
struct or unit enum variant");
870872
}
871873
}
872874
visit::walk_struct_def(self, s)

src/libsyntax/parse/parser.rs

Lines changed: 35 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ pub enum BoundParsingMode {
113113
Modified,
114114
}
115115

116+
/// `pub` should be parsed in struct fields and not parsed in variant fields
117+
#[derive(Clone, Copy, PartialEq)]
118+
pub enum ParsePub {
119+
Yes,
120+
No,
121+
}
122+
116123
/// Possibly accept an `token::Interpolated` expression (a pre-parsed expression
117124
/// dropped into the token stream, which happens while parsing the result of
118125
/// macro expansion). Placement of these is not as complex as I feared it would
@@ -4686,18 +4693,23 @@ impl<'a> Parser<'a> {
46864693
VariantData::Unit(ast::DUMMY_NODE_ID)
46874694
} else {
46884695
// If we see: `struct Foo<T> where T: Copy { ... }`
4689-
VariantData::Struct(try!(self.parse_record_struct_body()), ast::DUMMY_NODE_ID)
4696+
VariantData::Struct(try!(self.parse_record_struct_body(ParsePub::Yes)),
4697+
ast::DUMMY_NODE_ID)
46904698
}
46914699
// No `where` so: `struct Foo<T>;`
46924700
} else if try!(self.eat(&token::Semi) ){
46934701
VariantData::Unit(ast::DUMMY_NODE_ID)
46944702
// Record-style struct definition
46954703
} else if self.token == token::OpenDelim(token::Brace) {
4696-
VariantData::Struct(try!(self.parse_record_struct_body()), ast::DUMMY_NODE_ID)
4704+
VariantData::Struct(try!(self.parse_record_struct_body(ParsePub::Yes)),
4705+
ast::DUMMY_NODE_ID)
46974706
// Tuple-style struct definition with optional where-clause.
46984707
} else if self.token == token::OpenDelim(token::Paren) {
4699-
VariantData::Tuple(try!(self.parse_tuple_struct_body(&mut generics)),
4700-
ast::DUMMY_NODE_ID)
4708+
let body = VariantData::Tuple(try!(self.parse_tuple_struct_body(ParsePub::Yes)),
4709+
ast::DUMMY_NODE_ID);
4710+
generics.where_clause = try!(self.parse_where_clause());
4711+
try!(self.expect(&token::Semi));
4712+
body
47014713
} else {
47024714
let token_str = self.this_token_to_string();
47034715
return Err(self.fatal(&format!("expected `where`, `{{`, `(`, or `;` after struct \
@@ -4707,11 +4719,11 @@ impl<'a> Parser<'a> {
47074719
Ok((class_name, ItemStruct(vdata, generics), None))
47084720
}
47094721

4710-
pub fn parse_record_struct_body(&mut self) -> PResult<Vec<StructField>> {
4722+
pub fn parse_record_struct_body(&mut self, parse_pub: ParsePub) -> PResult<Vec<StructField>> {
47114723
let mut fields = Vec::new();
47124724
if try!(self.eat(&token::OpenDelim(token::Brace)) ){
47134725
while self.token != token::CloseDelim(token::Brace) {
4714-
fields.push(try!(self.parse_struct_decl_field(true)));
4726+
fields.push(try!(self.parse_struct_decl_field(parse_pub)));
47154727
}
47164728

47174729
try!(self.bump());
@@ -4725,9 +4737,7 @@ impl<'a> Parser<'a> {
47254737
Ok(fields)
47264738
}
47274739

4728-
pub fn parse_tuple_struct_body(&mut self,
4729-
generics: &mut ast::Generics)
4730-
-> PResult<Vec<StructField>> {
4740+
pub fn parse_tuple_struct_body(&mut self, parse_pub: ParsePub) -> PResult<Vec<StructField>> {
47314741
// This is the case where we find `struct Foo<T>(T) where T: Copy;`
47324742
// Unit like structs are handled in parse_item_struct function
47334743
let fields = try!(self.parse_unspanned_seq(
@@ -4738,16 +4748,20 @@ impl<'a> Parser<'a> {
47384748
let attrs = try!(p.parse_outer_attributes());
47394749
let lo = p.span.lo;
47404750
let struct_field_ = ast::StructField_ {
4741-
kind: UnnamedField(try!(p.parse_visibility())),
4751+
kind: UnnamedField (
4752+
if parse_pub == ParsePub::Yes {
4753+
try!(p.parse_visibility())
4754+
} else {
4755+
Inherited
4756+
}
4757+
),
47424758
id: ast::DUMMY_NODE_ID,
47434759
ty: try!(p.parse_ty_sum()),
47444760
attrs: attrs,
47454761
};
47464762
Ok(spanned(lo, p.span.hi, struct_field_))
47474763
}));
47484764

4749-
generics.where_clause = try!(self.parse_where_clause());
4750-
try!(self.expect(&token::Semi));
47514765
Ok(fields)
47524766
}
47534767

@@ -4775,12 +4789,12 @@ impl<'a> Parser<'a> {
47754789
}
47764790

47774791
/// Parse an element of a struct definition
4778-
fn parse_struct_decl_field(&mut self, allow_pub: bool) -> PResult<StructField> {
4792+
fn parse_struct_decl_field(&mut self, parse_pub: ParsePub) -> PResult<StructField> {
47794793

47804794
let attrs = try!(self.parse_outer_attributes());
47814795

47824796
if try!(self.eat_keyword(keywords::Pub) ){
4783-
if !allow_pub {
4797+
if parse_pub == ParsePub::No {
47844798
let span = self.last_span;
47854799
self.span_err(span, "`pub` is not allowed here");
47864800
}
@@ -5133,18 +5147,6 @@ impl<'a> Parser<'a> {
51335147
Ok((ident, ItemTy(ty, tps), None))
51345148
}
51355149

5136-
/// Parse a structure-like enum variant definition
5137-
/// this should probably be renamed or refactored...
5138-
fn parse_struct_def(&mut self) -> PResult<VariantData> {
5139-
let mut fields: Vec<StructField> = Vec::new();
5140-
while self.token != token::CloseDelim(token::Brace) {
5141-
fields.push(try!(self.parse_struct_decl_field(false)));
5142-
}
5143-
try!(self.bump());
5144-
5145-
Ok(VariantData::Struct(fields, ast::DUMMY_NODE_ID))
5146-
}
5147-
51485150
/// Parse the part of an "enum" decl following the '{'
51495151
fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<EnumDef> {
51505152
let mut variants = Vec::new();
@@ -5157,34 +5159,21 @@ impl<'a> Parser<'a> {
51575159
let struct_def;
51585160
let mut disr_expr = None;
51595161
let ident = try!(self.parse_ident());
5160-
if try!(self.eat(&token::OpenDelim(token::Brace)) ){
5162+
if self.check(&token::OpenDelim(token::Brace)) {
51615163
// Parse a struct variant.
51625164
all_nullary = false;
5163-
struct_def = try!(self.parse_struct_def());
5165+
struct_def = VariantData::Struct(try!(self.parse_record_struct_body(ParsePub::No)),
5166+
ast::DUMMY_NODE_ID);
51645167
} else if self.check(&token::OpenDelim(token::Paren)) {
51655168
all_nullary = false;
5166-
let arg_tys = try!(self.parse_enum_variant_seq(
5167-
&token::OpenDelim(token::Paren),
5168-
&token::CloseDelim(token::Paren),
5169-
seq_sep_trailing_allowed(token::Comma),
5170-
|p| p.parse_ty_sum()
5171-
));
5172-
let mut fields = Vec::new();
5173-
for ty in arg_tys {
5174-
fields.push(Spanned { span: ty.span, node: ast::StructField_ {
5175-
ty: ty,
5176-
kind: ast::UnnamedField(ast::Inherited),
5177-
attrs: Vec::new(),
5178-
id: ast::DUMMY_NODE_ID,
5179-
}});
5180-
}
5181-
struct_def = ast::VariantData::Tuple(fields, ast::DUMMY_NODE_ID);
5169+
struct_def = VariantData::Tuple(try!(self.parse_tuple_struct_body(ParsePub::No)),
5170+
ast::DUMMY_NODE_ID);
51825171
} else if try!(self.eat(&token::Eq) ){
51835172
disr_expr = Some(try!(self.parse_expr_nopanic()));
51845173
any_disr = disr_expr.as_ref().map(|expr| expr.span);
5185-
struct_def = ast::VariantData::Unit(ast::DUMMY_NODE_ID);
5174+
struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
51865175
} else {
5187-
struct_def = ast::VariantData::Unit(ast::DUMMY_NODE_ID);
5176+
struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
51885177
}
51895178

51905179
let vr = ast::Variant_ {

src/test/parse-fail/issue-12560-1.rs renamed to src/test/compile-fail/issue-12560-1.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// compile-flags: -Z parse-only
12-
1311
// For style and consistency reasons, non-parametrized enum variants must
1412
// be used simply as `ident` instead of `ident ()`.
1513
// This test-case covers enum declaration.
1614

1715
enum Foo {
18-
Bar(), //~ ERROR nullary enum variants are written with no trailing `( )`
19-
Baz(), //~ ERROR nullary enum variants are written with no trailing `( )`
16+
Bar(), //~ ERROR empty tuple structs and enum variants are not allowed
17+
//~^ HELP remove trailing `()` to make a unit struct or unit enum variant
18+
Baz(), //~ ERROR empty tuple structs and enum variants are not allowed
19+
//~^ HELP remove trailing `()` to make a unit struct or unit enum variant
2020
Bazar
2121
}
2222

src/test/compile-fail/issue-16819.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,17 @@
1010

1111
struct TS ( //~ ERROR empty tuple structs and enum variants are not allowed
1212
#[cfg(untrue)]
13-
int,
13+
i32,
1414
);
1515

16+
enum E {
17+
TV ( //~ ERROR empty tuple structs and enum variants are not allowed
18+
#[cfg(untrue)]
19+
i32,
20+
)
21+
}
22+
1623
fn main() {
17-
let s = S;
24+
let s = TS;
25+
let tv = E::TV;
1826
}

0 commit comments

Comments
 (0)