diff --git a/src/doc/reference.md b/src/doc/reference.md index 18feebf3d5689..83849574260e1 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1178,11 +1178,22 @@ let px: i32 = match p { Point(x, _) => x }; ``` A _unit-like struct_ is a structure without any fields, defined by leaving off -the list of fields entirely. Such types will have a single value. For example: +the list of fields entirely. Such a structure implicitly defines a constant of +its type with the same name. For example: ``` +# #![feature(braced_empty_structs)] struct Cookie; -let c = [Cookie, Cookie, Cookie, Cookie]; +let c = [Cookie, Cookie {}, Cookie, Cookie {}]; +``` + +is equivalent to + +``` +# #![feature(braced_empty_structs)] +struct Cookie {} +const Cookie: Cookie = Cookie {}; +let c = [Cookie, Cookie {}, Cookie, Cookie {}]; ``` The precise memory layout of a structure is not specified. One can specify a @@ -2411,6 +2422,7 @@ The currently implemented features of the reference compiler are: terms of encapsulation). * - `default_type_parameter_fallback` - Allows type parameter defaults to influence type inference. +* - `braced_empty_structs` - Allows use of empty structs with braces. If a feature is promoted to a language feature, then all existing programs will start to receive compilation warnings about `#![feature]` directives which enabled diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs index d4a52a5ed8eb0..940145aa4173b 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
>) -> 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 e5dbfdf176739..6f1e2e283e7a2 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/feature_gate.rs b/src/libsyntax/feature_gate.rs
index abc0410295055..989977a691755 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 >) -> 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
similarity index 59%
rename from src/test/parse-fail/struct-no-fields-2.rs
rename to src/test/compile-fail/empty-struct-with-braces-1.rs
index 1e6169f285b5c..ad412259faa29 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,12 @@
// 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;
+#![feature(braced_empty_structs)]
-fn f2() {
- let _end_stmt = Foo { };
- //~^ ERROR: structure literal must either have at least one field
-}
+struct Empty {}
-fn main() {}
+fn main() {
+ let e = Empty; //~ ERROR `Empty` is the name of a struct or struct variant
+}
diff --git a/src/test/parse-fail/struct-no-fields-4.rs b/src/test/compile-fail/empty-struct-with-braces-2.rs
similarity index 50%
rename from src/test/parse-fail/struct-no-fields-4.rs
rename to src/test/compile-fail/empty-struct-with-braces-2.rs
index 6e55baf06cedf..0e72e7dc44185 100644
--- a/src/test/parse-fail/struct-no-fields-4.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,18 @@
// 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;
+#![feature(braced_empty_structs)]
+#![deny(warnings)]
-fn h4() {
- let _end_of_tuple = (3, Foo { });
- //~^ 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/parse-fail/struct-no-fields-3.rs b/src/test/compile-fail/empty-struct-with-braces-3.rs
similarity index 53%
rename from src/test/parse-fail/struct-no-fields-3.rs
rename to src/test/compile-fail/empty-struct-with-braces-3.rs
index 8e72151ffe979..e6f20ba345ad3 100644
--- a/src/test/parse-fail/struct-no-fields-3.rs
+++ b/src/test/compile-fail/empty-struct-with-braces-3.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,14 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// compile-flags: -Z parse-only
+// Feature gate test for empty struct with braces
-struct Foo;
+struct Empty {} //~ ERROR empty structs with braces are unstable
-fn g3() {
- let _mid_tuple = (Foo { }, 2);
- //~^ ERROR: structure literal must either have at least one field
-}
+fn main() {
+ let e = Empty {}; //~ ERROR empty structs with braces are unstable
-fn main() {}
+ match e {
+ Empty {} => {} //~ ERROR empty structs with braces are unstable
+ }
+}
diff --git a/src/test/compile-fail/issue-27831.rs b/src/test/compile-fail/issue-27831.rs
index 336368cf8a49d..533387c576008 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-5.rs b/src/test/parse-fail/struct-no-fields-5.rs
deleted file mode 100644
index 5f92d98606693..0000000000000
--- 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