diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2015-10-02 22:41:24 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2015-10-13 15:19:20 +0300 |
| commit | 8a12c19171887ea6d7ff708db2e2581ceaf16c14 (patch) | |
| tree | 2ff02dad84730da28dc96d487d96a442350ee320 /src/libsyntax | |
| parent | beda1f88a7d87cf994fe8e3a5b2fe126e31fcae9 (diff) | |
| download | rust-8a12c19171887ea6d7ff708db2e2581ceaf16c14.tar.gz rust-8a12c19171887ea6d7ff708db2e2581ceaf16c14.zip | |
Test and gate empty structures and variants better
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 38 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 9 |
2 files changed, 21 insertions, 26 deletions
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 0b3af659a7b..66a422ce664 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -196,7 +196,7 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status // allow `#[unwind]` ("unwind_attributes", "1.4.0", None, Active), - // allow empty structs/enum variants with braces + // allow empty structs and enum variants with braces ("braced_empty_structs", "1.5.0", None, Active), // allow overloading augmented assignment operations like `a += b` @@ -486,6 +486,7 @@ pub struct Features { pub cfg_target_feature: bool, pub cfg_target_vendor: bool, pub augmented_assignments: bool, + pub braced_empty_structs: bool, } impl Features { @@ -516,6 +517,7 @@ impl Features { cfg_target_feature: false, cfg_target_vendor: false, augmented_assignments: false, + braced_empty_structs: false, } } } @@ -809,7 +811,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { } } - ast::ItemStruct(ref def, _) => { + ast::ItemStruct(..) => { if attr::contains_name(&i.attrs[..], "simd") { self.gate_feature("simd", i.span, "SIMD types are experimental and possibly buggy"); @@ -828,10 +830,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { } } } - if def.fields.is_empty() && def.kind == ast::VariantKind::Dict { - self.gate_feature("braced_empty_structs", i.span, - "empty structs with braces are unstable"); - } } ast::ItemDefaultImpl(..) => { @@ -859,6 +857,21 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { visit::walk_item(self, i); } + fn visit_struct_def(&mut self, s: &'v ast::StructDef, _: ast::Ident, + _: &'v ast::Generics, _: ast::NodeId, span: Span) { + if s.fields.is_empty() { + if s.kind == ast::VariantKind::Dict { + self.gate_feature("braced_empty_structs", span, + "empty structs and enum variants with braces are unstable"); + } else if s.kind == ast::VariantKind::Tuple { + self.context.span_handler.span_err(span, "empty tuple structs and enum variants \ + are not allowed, use unit structs and \ + enum variants instead"); + } + } + visit::walk_struct_def(self, s) + } + fn visit_foreign_item(&mut self, i: &ast::ForeignItem) { let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") { @@ -881,12 +894,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { "box expression syntax is experimental; \ you can call `Box::new` instead."); } - ast::ExprStruct(_, ref fields, ref expr) => { - if fields.is_empty() && expr.is_none() { - self.gate_feature("braced_empty_structs", e.span, - "empty structs with braces are unstable"); - } - } _ => {} } visit::walk_expr(self, e); @@ -911,12 +918,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { pattern.span, "box pattern syntax is experimental"); } - ast::PatStruct(_, ref fields, dotdot) => { - if fields.is_empty() && !dotdot { - self.gate_feature("braced_empty_structs", pattern.span, - "empty structs with braces are unstable"); - } - } _ => {} } visit::walk_pat(self, pattern) @@ -1086,6 +1087,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, cfg_target_feature: cx.has_feature("cfg_target_feature"), cfg_target_vendor: cx.has_feature("cfg_target_vendor"), augmented_assignments: cx.has_feature("augmented_assignments"), + braced_empty_structs: cx.has_feature("braced_empty_structs"), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 09ca20653ed..47632781956 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4658,7 +4658,7 @@ impl<'a> Parser<'a> { (fields, VariantKind::Dict) // Tuple-style struct definition with optional where-clause. } else if self.token == token::OpenDelim(token::Paren) { - let fields = try!(self.parse_tuple_struct_body(class_name, &mut generics)); + let fields = try!(self.parse_tuple_struct_body(&mut generics)); (fields, VariantKind::Tuple) } else { let token_str = self.this_token_to_string(); @@ -4694,7 +4694,6 @@ impl<'a> Parser<'a> { } pub fn parse_tuple_struct_body(&mut self, - class_name: ast::Ident, generics: &mut ast::Generics) -> PResult<Vec<StructField>> { // This is the case where we find `struct Foo<T>(T) where T: Copy;` @@ -4715,12 +4714,6 @@ impl<'a> Parser<'a> { Ok(spanned(lo, p.span.hi, struct_field_)) })); - if fields.is_empty() { - return Err(self.fatal(&format!("unit-like struct definition should be \ - written as `struct {};`", - class_name))); - } - generics.where_clause = try!(self.parse_where_clause()); try!(self.expect(&token::Semi)); Ok(fields) |
