about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2015-09-10 22:46:52 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2015-09-18 15:26:08 +0300
commit5fa6e857c9f43a69661ebca278c99155ee7d5db7 (patch)
treef10c986188ac45cbd1e7b9789f9f2ddedeb6e16d
parentcff04117064ddee95f425c49f22c8aa5a3a665d4 (diff)
downloadrust-5fa6e857c9f43a69661ebca278c99155ee7d5db7.tar.gz
rust-5fa6e857c9f43a69661ebca278c99155ee7d5db7.zip
Implement empty struct with braces (RFC 218)
-rw-r--r--src/librustc_front/print/pprust.rs50
-rw-r--r--src/librustc_typeck/check/mod.rs4
-rw-r--r--src/libsyntax/parse/parser.rs21
-rw-r--r--src/libsyntax/print/pprust.rs50
-rw-r--r--src/test/compile-fail/empty-struct-with-braces-1.rs (renamed from src/test/parse-fail/struct-no-fields-2.rs)13
-rw-r--r--src/test/compile-fail/empty-struct-with-braces-2.rs (renamed from src/test/parse-fail/struct-no-fields-3.rs)20
-rw-r--r--src/test/compile-fail/issue-27831.rs4
-rw-r--r--src/test/parse-fail/struct-no-fields-4.rs20
-rw-r--r--src/test/parse-fail/struct-no-fields-5.rs20
-rw-r--r--src/test/run-pass/empty-struct-with-braces.rs31
-rw-r--r--src/test/run-pass/issue-16819.rs (renamed from src/test/parse-fail/struct-no-fields.rs)14
11 files changed, 114 insertions, 133 deletions
diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs
index d4a52a5ed8e..940145aa417 100644
--- a/src/librustc_front/print/pprust.rs
+++ b/src/librustc_front/print/pprust.rs
@@ -1218,34 +1218,34 @@ impl<'a> State<'a> {
                          fields: &[hir::Field],
                          wth: &Option<P<hir::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(())
     }
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index e5dbfdf1767..6f1e2e283e7 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1473,14 +1473,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => return None
         };
 
-        if let ty::VariantKind::Dict = variant.kind() {
+        let var_kind = variant.kind();
+        if var_kind == ty::VariantKind::Dict || var_kind == ty::VariantKind::Unit {
             Some((adt, variant))
         } else {
             None
         }
     }
 
-
     pub fn write_nil(&self, node_id: ast::NodeId) {
         self.write_ty(node_id, self.tcx().mk_nil());
     }
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(())
     }
 
diff --git a/src/test/parse-fail/struct-no-fields-2.rs b/src/test/compile-fail/empty-struct-with-braces-1.rs
index 1e6169f285b..bfe72856a2e 100644
--- a/src/test/parse-fail/struct-no-fields-2.rs
+++ b/src/test/compile-fail/empty-struct-with-braces-1.rs
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,13 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z parse-only
+// Empty struct defined with braces shouldn't add names into value namespace
 
-struct Foo;
+struct Empty {}
 
-fn f2() {
-    let _end_stmt     = Foo { };
-    //~^ ERROR: structure literal must either have at least one field
+fn main() {
+    let e = Empty; //~ ERROR `Empty` is the name of a struct or struct variant
 }
-
-fn main() {}
diff --git a/src/test/parse-fail/struct-no-fields-3.rs b/src/test/compile-fail/empty-struct-with-braces-2.rs
index 8e72151ffe9..7e5a87fe1a4 100644
--- a/src/test/parse-fail/struct-no-fields-3.rs
+++ b/src/test/compile-fail/empty-struct-with-braces-2.rs
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,13 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z parse-only
+// Empty struct defined with braces shouldn't add names into value namespace
 
-struct Foo;
+#![deny(warnings)]
 
-fn g3() {
-    let _mid_tuple    = (Foo { }, 2);
-    //~^ ERROR: structure literal must either have at least one field
-}
+struct Empty {}
+
+fn main() {
+    let e = Empty {};
 
-fn main() {}
+    match e {
+        Empty => () //~ ERROR unused variable: `Empty`
+        //~^ ERROR variable `Empty` should have a snake case name such as `empty`
+    }
+}
diff --git a/src/test/compile-fail/issue-27831.rs b/src/test/compile-fail/issue-27831.rs
index 336368cf8a4..533387c5760 100644
--- a/src/test/compile-fail/issue-27831.rs
+++ b/src/test/compile-fail/issue-27831.rs
@@ -22,8 +22,8 @@ fn main() {
     let Foo { .. } = x; //~ ERROR `Foo` does not name a struct
 
     let x = Bar;
-    Bar { ..x }; //~ ERROR `Bar` does not name a structure
-    let Bar { .. } = x; //~ ERROR `Bar` does not name a struct
+    Bar { ..x };
+    let Bar { .. } = x;
 
     match Enum::Bar {
         Enum::Bar { .. } //~ ERROR `Enum::Bar` does not name a struct
diff --git a/src/test/parse-fail/struct-no-fields-4.rs b/src/test/parse-fail/struct-no-fields-4.rs
deleted file mode 100644
index 6e55baf06ce..00000000000
--- a/src/test/parse-fail/struct-no-fields-4.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z parse-only
-
-struct Foo;
-
-fn h4() {
-    let _end_of_tuple = (3, Foo { });
-    //~^ ERROR: structure literal must either have at least one field
-}
-
-fn main() {}
diff --git a/src/test/parse-fail/struct-no-fields-5.rs b/src/test/parse-fail/struct-no-fields-5.rs
deleted file mode 100644
index 5f92d986066..00000000000
--- a/src/test/parse-fail/struct-no-fields-5.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z parse-only
-
-struct Foo;
-
-fn i5() {
-    let _end_of_block = { Foo { } };
-    //~^ ERROR: structure literal must either have at least one field
-}
-
-fn main() {}
diff --git a/src/test/run-pass/empty-struct-with-braces.rs b/src/test/run-pass/empty-struct-with-braces.rs
new file mode 100644
index 00000000000..a96c1e5b10c
--- /dev/null
+++ b/src/test/run-pass/empty-struct-with-braces.rs
@@ -0,0 +1,31 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Empty struct defined with braces add names into type namespace
+// Empty struct defined without braces add names into both type and value namespaces
+
+struct Empty1 {}
+struct Empty2;
+
+fn main() {
+    let e1: Empty1 = Empty1 {};
+    let e2: Empty2 = Empty2 {};
+    let e2: Empty2 = Empty2;
+
+    match e1 {
+        Empty1 {} => ()
+    }
+    match e2 {
+        Empty2 {} => ()
+    }
+    match e2 {
+        Empty2 => ()
+    }
+}
diff --git a/src/test/parse-fail/struct-no-fields.rs b/src/test/run-pass/issue-16819.rs
index fa5065b7630..fb35ce33157 100644
--- a/src/test/parse-fail/struct-no-fields.rs
+++ b/src/test/run-pass/issue-16819.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,9 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z parse-only
+//`#[cfg]` on struct field permits empty unusable struct
 
-struct Foo {}
-//~^ ERROR: unit-like struct definition should be written as `struct Foo;`
+struct S {
+    #[cfg(untrue)]
+    a: int,
+}
 
-fn main() {}
+fn main() {
+    let s = S {};
+}