summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-09-18 16:57:21 +0000
committerbors <bors@rust-lang.org>2015-09-18 16:57:21 +0000
commitdc1c7975b015c14d4c26f2b07ab2b64f5fc66d3c (patch)
tree90c8b72b7eecdde1c1f23df051fa712e196d7291 /src/libsyntax
parent53ba768b8a88a72cb96e8ff9b76ec36797ba2acd (diff)
parent1eb42f1c784e999259b15f68c63040e1fafbe273 (diff)
downloadrust-dc1c7975b015c14d4c26f2b07ab2b64f5fc66d3c.tar.gz
rust-dc1c7975b015c14d4c26f2b07ab2b64f5fc66d3c.zip
Auto merge of #28336 - petrochenkov:empstr, r=pnkfelix
Closes https://github.com/rust-lang/rust/issues/24266
Closes https://github.com/rust-lang/rust/issues/16819
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/feature_gate.rs21
-rw-r--r--src/libsyntax/parse/parser.rs21
-rw-r--r--src/libsyntax/print/pprust.rs50
3 files changed, 48 insertions, 44 deletions
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index abc04102950..989977a6917 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -191,6 +191,9 @@ 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
+    ("braced_empty_structs", "1.5.0", None, Active),
 ];
 // (changing above list without updating src/doc/reference.md makes @cmr sad)
 
@@ -775,7 +778,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
                 }
             }
 
-            ast::ItemStruct(..) => {
+            ast::ItemStruct(ref def, _) => {
                 if attr::contains_name(&i.attrs[..], "simd") {
                     self.gate_feature("simd", i.span,
                                       "SIMD types are experimental and possibly buggy");
@@ -794,6 +797,10 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
                         }
                     }
                 }
+                if def.fields.is_empty() && def.ctor_id.is_none() {
+                    self.gate_feature("braced_empty_structs", i.span,
+                                      "empty structs with braces are unstable");
+                }
             }
 
             ast::ItemDefaultImpl(..) => {
@@ -843,6 +850,12 @@ 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);
@@ -867,6 +880,12 @@ 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)
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index b6650b6f944..a7978babcb7 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2231,14 +2231,6 @@ impl<'a> Parser<'a> {
                                                  &[token::CloseDelim(token::Brace)]));
                             }
 
-                            if fields.is_empty() && base.is_none() {
-                                let last_span = self.last_span;
-                                self.span_err(last_span,
-                                              "structure literal must either \
-                                              have at least one field or use \
-                                              structure update syntax");
-                            }
-
                             hi = self.span.hi;
                             try!(self.expect(&token::CloseDelim(token::Brace)));
                             ex = ExprStruct(pth, fields, base);
@@ -4713,14 +4705,14 @@ impl<'a> Parser<'a> {
                 (Vec::new(), Some(ast::DUMMY_NODE_ID))
             } else {
                 // If we see: `struct Foo<T> where T: Copy { ... }`
-                (try!(self.parse_record_struct_body(&class_name)), None)
+                (try!(self.parse_record_struct_body()), None)
             }
         // No `where` so: `struct Foo<T>;`
         } else if try!(self.eat(&token::Semi) ){
             (Vec::new(), Some(ast::DUMMY_NODE_ID))
         // Record-style struct definition
         } else if self.token == token::OpenDelim(token::Brace) {
-            let fields = try!(self.parse_record_struct_body(&class_name));
+            let fields = try!(self.parse_record_struct_body());
             (fields, None)
         // Tuple-style struct definition with optional where-clause.
         } else if self.token == token::OpenDelim(token::Paren) {
@@ -4740,20 +4732,13 @@ impl<'a> Parser<'a> {
          None))
     }
 
-    pub fn parse_record_struct_body(&mut self,
-                                    class_name: &ast::Ident) -> PResult<Vec<StructField>> {
+    pub fn parse_record_struct_body(&mut self) -> PResult<Vec<StructField>> {
         let mut fields = Vec::new();
         if try!(self.eat(&token::OpenDelim(token::Brace)) ){
             while self.token != token::CloseDelim(token::Brace) {
                 fields.push(try!(self.parse_struct_decl_field(true)));
             }
 
-            if fields.is_empty() {
-                return Err(self.fatal(&format!("unit-like struct definition should be \
-                    written as `struct {};`",
-                    class_name)));
-            }
-
             try!(self.bump());
         } else {
             let token_str = self.this_token_to_string();
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index b00ff85051c..1d22c83122e 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1855,34 +1855,34 @@ impl<'a> State<'a> {
                          fields: &[ast::Field],
                          wth: &Option<P<ast::Expr>>) -> io::Result<()> {
         try!(self.print_path(path, true, 0));
-        if !(fields.is_empty() && wth.is_none()) {
-            try!(word(&mut self.s, "{"));
-            try!(self.commasep_cmnt(
-                Consistent,
-                &fields[..],
-                |s, field| {
-                    try!(s.ibox(indent_unit));
-                    try!(s.print_ident(field.ident.node));
-                    try!(s.word_space(":"));
-                    try!(s.print_expr(&*field.expr));
-                    s.end()
-                },
-                |f| f.span));
-            match *wth {
-                Some(ref expr) => {
-                    try!(self.ibox(indent_unit));
-                    if !fields.is_empty() {
-                        try!(word(&mut self.s, ","));
-                        try!(space(&mut self.s));
-                    }
-                    try!(word(&mut self.s, ".."));
-                    try!(self.print_expr(&**expr));
-                    try!(self.end());
+        try!(word(&mut self.s, "{"));
+        try!(self.commasep_cmnt(
+            Consistent,
+            &fields[..],
+            |s, field| {
+                try!(s.ibox(indent_unit));
+                try!(s.print_ident(field.ident.node));
+                try!(s.word_space(":"));
+                try!(s.print_expr(&*field.expr));
+                s.end()
+            },
+            |f| f.span));
+        match *wth {
+            Some(ref expr) => {
+                try!(self.ibox(indent_unit));
+                if !fields.is_empty() {
+                    try!(word(&mut self.s, ","));
+                    try!(space(&mut self.s));
                 }
-                _ => try!(word(&mut self.s, ",")),
+                try!(word(&mut self.s, ".."));
+                try!(self.print_expr(&**expr));
+                try!(self.end());
+            }
+            _ => if !fields.is_empty() {
+                try!(word(&mut self.s, ","))
             }
-            try!(word(&mut self.s, "}"));
         }
+        try!(word(&mut self.s, "}"));
         Ok(())
     }