Skip to content

Commit 5fa6e85

Browse files
committed
Implement empty struct with braces (RFC 218)
1 parent cff0411 commit 5fa6e85

File tree

11 files changed

+114
-133
lines changed

11 files changed

+114
-133
lines changed

src/librustc_front/print/pprust.rs

+25-25
Original file line numberDiff line numberDiff line change
@@ -1218,34 +1218,34 @@ impl<'a> State<'a> {
12181218
fields: &[hir::Field],
12191219
wth: &Option<P<hir::Expr>>) -> io::Result<()> {
12201220
try!(self.print_path(path, true, 0));
1221-
if !(fields.is_empty() && wth.is_none()) {
1222-
try!(word(&mut self.s, "{"));
1223-
try!(self.commasep_cmnt(
1224-
Consistent,
1225-
&fields[..],
1226-
|s, field| {
1227-
try!(s.ibox(indent_unit));
1228-
try!(s.print_ident(field.ident.node));
1229-
try!(s.word_space(":"));
1230-
try!(s.print_expr(&*field.expr));
1231-
s.end()
1232-
},
1233-
|f| f.span));
1234-
match *wth {
1235-
Some(ref expr) => {
1236-
try!(self.ibox(indent_unit));
1237-
if !fields.is_empty() {
1238-
try!(word(&mut self.s, ","));
1239-
try!(space(&mut self.s));
1240-
}
1241-
try!(word(&mut self.s, ".."));
1242-
try!(self.print_expr(&**expr));
1243-
try!(self.end());
1221+
try!(word(&mut self.s, "{"));
1222+
try!(self.commasep_cmnt(
1223+
Consistent,
1224+
&fields[..],
1225+
|s, field| {
1226+
try!(s.ibox(indent_unit));
1227+
try!(s.print_ident(field.ident.node));
1228+
try!(s.word_space(":"));
1229+
try!(s.print_expr(&*field.expr));
1230+
s.end()
1231+
},
1232+
|f| f.span));
1233+
match *wth {
1234+
Some(ref expr) => {
1235+
try!(self.ibox(indent_unit));
1236+
if !fields.is_empty() {
1237+
try!(word(&mut self.s, ","));
1238+
try!(space(&mut self.s));
12441239
}
1245-
_ => try!(word(&mut self.s, ",")),
1240+
try!(word(&mut self.s, ".."));
1241+
try!(self.print_expr(&**expr));
1242+
try!(self.end());
1243+
}
1244+
_ => if !fields.is_empty() {
1245+
try!(word(&mut self.s, ","))
12461246
}
1247-
try!(word(&mut self.s, "}"));
12481247
}
1248+
try!(word(&mut self.s, "}"));
12491249
Ok(())
12501250
}
12511251

src/librustc_typeck/check/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1473,14 +1473,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14731473
_ => return None
14741474
};
14751475

1476-
if let ty::VariantKind::Dict = variant.kind() {
1476+
let var_kind = variant.kind();
1477+
if var_kind == ty::VariantKind::Dict || var_kind == ty::VariantKind::Unit {
14771478
Some((adt, variant))
14781479
} else {
14791480
None
14801481
}
14811482
}
14821483

1483-
14841484
pub fn write_nil(&self, node_id: ast::NodeId) {
14851485
self.write_ty(node_id, self.tcx().mk_nil());
14861486
}

src/libsyntax/parse/parser.rs

+3-18
Original file line numberDiff line numberDiff line change
@@ -2231,14 +2231,6 @@ impl<'a> Parser<'a> {
22312231
&[token::CloseDelim(token::Brace)]));
22322232
}
22332233

2234-
if fields.is_empty() && base.is_none() {
2235-
let last_span = self.last_span;
2236-
self.span_err(last_span,
2237-
"structure literal must either \
2238-
have at least one field or use \
2239-
structure update syntax");
2240-
}
2241-
22422234
hi = self.span.hi;
22432235
try!(self.expect(&token::CloseDelim(token::Brace)));
22442236
ex = ExprStruct(pth, fields, base);
@@ -4713,14 +4705,14 @@ impl<'a> Parser<'a> {
47134705
(Vec::new(), Some(ast::DUMMY_NODE_ID))
47144706
} else {
47154707
// If we see: `struct Foo<T> where T: Copy { ... }`
4716-
(try!(self.parse_record_struct_body(&class_name)), None)
4708+
(try!(self.parse_record_struct_body()), None)
47174709
}
47184710
// No `where` so: `struct Foo<T>;`
47194711
} else if try!(self.eat(&token::Semi) ){
47204712
(Vec::new(), Some(ast::DUMMY_NODE_ID))
47214713
// Record-style struct definition
47224714
} else if self.token == token::OpenDelim(token::Brace) {
4723-
let fields = try!(self.parse_record_struct_body(&class_name));
4715+
let fields = try!(self.parse_record_struct_body());
47244716
(fields, None)
47254717
// Tuple-style struct definition with optional where-clause.
47264718
} else if self.token == token::OpenDelim(token::Paren) {
@@ -4740,20 +4732,13 @@ impl<'a> Parser<'a> {
47404732
None))
47414733
}
47424734

4743-
pub fn parse_record_struct_body(&mut self,
4744-
class_name: &ast::Ident) -> PResult<Vec<StructField>> {
4735+
pub fn parse_record_struct_body(&mut self) -> PResult<Vec<StructField>> {
47454736
let mut fields = Vec::new();
47464737
if try!(self.eat(&token::OpenDelim(token::Brace)) ){
47474738
while self.token != token::CloseDelim(token::Brace) {
47484739
fields.push(try!(self.parse_struct_decl_field(true)));
47494740
}
47504741

4751-
if fields.is_empty() {
4752-
return Err(self.fatal(&format!("unit-like struct definition should be \
4753-
written as `struct {};`",
4754-
class_name)));
4755-
}
4756-
47574742
try!(self.bump());
47584743
} else {
47594744
let token_str = self.this_token_to_string();

src/libsyntax/print/pprust.rs

+25-25
Original file line numberDiff line numberDiff line change
@@ -1855,34 +1855,34 @@ impl<'a> State<'a> {
18551855
fields: &[ast::Field],
18561856
wth: &Option<P<ast::Expr>>) -> io::Result<()> {
18571857
try!(self.print_path(path, true, 0));
1858-
if !(fields.is_empty() && wth.is_none()) {
1859-
try!(word(&mut self.s, "{"));
1860-
try!(self.commasep_cmnt(
1861-
Consistent,
1862-
&fields[..],
1863-
|s, field| {
1864-
try!(s.ibox(indent_unit));
1865-
try!(s.print_ident(field.ident.node));
1866-
try!(s.word_space(":"));
1867-
try!(s.print_expr(&*field.expr));
1868-
s.end()
1869-
},
1870-
|f| f.span));
1871-
match *wth {
1872-
Some(ref expr) => {
1873-
try!(self.ibox(indent_unit));
1874-
if !fields.is_empty() {
1875-
try!(word(&mut self.s, ","));
1876-
try!(space(&mut self.s));
1877-
}
1878-
try!(word(&mut self.s, ".."));
1879-
try!(self.print_expr(&**expr));
1880-
try!(self.end());
1858+
try!(word(&mut self.s, "{"));
1859+
try!(self.commasep_cmnt(
1860+
Consistent,
1861+
&fields[..],
1862+
|s, field| {
1863+
try!(s.ibox(indent_unit));
1864+
try!(s.print_ident(field.ident.node));
1865+
try!(s.word_space(":"));
1866+
try!(s.print_expr(&*field.expr));
1867+
s.end()
1868+
},
1869+
|f| f.span));
1870+
match *wth {
1871+
Some(ref expr) => {
1872+
try!(self.ibox(indent_unit));
1873+
if !fields.is_empty() {
1874+
try!(word(&mut self.s, ","));
1875+
try!(space(&mut self.s));
18811876
}
1882-
_ => try!(word(&mut self.s, ",")),
1877+
try!(word(&mut self.s, ".."));
1878+
try!(self.print_expr(&**expr));
1879+
try!(self.end());
1880+
}
1881+
_ => if !fields.is_empty() {
1882+
try!(word(&mut self.s, ","))
18831883
}
1884-
try!(word(&mut self.s, "}"));
18851884
}
1885+
try!(word(&mut self.s, "}"));
18861886
Ok(())
18871887
}
18881888

Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -8,13 +8,10 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// compile-flags: -Z parse-only
11+
// Empty struct defined with braces shouldn't add names into value namespace
1212

13-
struct Foo;
13+
struct Empty {}
1414

15-
fn f2() {
16-
let _end_stmt = Foo { };
17-
//~^ ERROR: structure literal must either have at least one field
15+
fn main() {
16+
let e = Empty; //~ ERROR `Empty` is the name of a struct or struct variant
1817
}
19-
20-
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -8,13 +8,17 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// compile-flags: -Z parse-only
11+
// Empty struct defined with braces shouldn't add names into value namespace
1212

13-
struct Foo;
13+
#![deny(warnings)]
1414

15-
fn g3() {
16-
let _mid_tuple = (Foo { }, 2);
17-
//~^ ERROR: structure literal must either have at least one field
18-
}
15+
struct Empty {}
16+
17+
fn main() {
18+
let e = Empty {};
1919

20-
fn main() {}
20+
match e {
21+
Empty => () //~ ERROR unused variable: `Empty`
22+
//~^ ERROR variable `Empty` should have a snake case name such as `empty`
23+
}
24+
}

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ fn main() {
2222
let Foo { .. } = x; //~ ERROR `Foo` does not name a struct
2323

2424
let x = Bar;
25-
Bar { ..x }; //~ ERROR `Bar` does not name a structure
26-
let Bar { .. } = x; //~ ERROR `Bar` does not name a struct
25+
Bar { ..x };
26+
let Bar { .. } = x;
2727

2828
match Enum::Bar {
2929
Enum::Bar { .. } //~ ERROR `Enum::Bar` does not name a struct

src/test/parse-fail/struct-no-fields-4.rs

-20
This file was deleted.

src/test/parse-fail/struct-no-fields-5.rs

-20
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Empty struct defined with braces add names into type namespace
12+
// Empty struct defined without braces add names into both type and value namespaces
13+
14+
struct Empty1 {}
15+
struct Empty2;
16+
17+
fn main() {
18+
let e1: Empty1 = Empty1 {};
19+
let e2: Empty2 = Empty2 {};
20+
let e2: Empty2 = Empty2;
21+
22+
match e1 {
23+
Empty1 {} => ()
24+
}
25+
match e2 {
26+
Empty2 {} => ()
27+
}
28+
match e2 {
29+
Empty2 => ()
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -8,9 +8,13 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// compile-flags: -Z parse-only
11+
//`#[cfg]` on struct field permits empty unusable struct
1212

13-
struct Foo {}
14-
//~^ ERROR: unit-like struct definition should be written as `struct Foo;`
13+
struct S {
14+
#[cfg(untrue)]
15+
a: int,
16+
}
1517

16-
fn main() {}
18+
fn main() {
19+
let s = S {};
20+
}

0 commit comments

Comments
 (0)