提交 5fa6e857 编写于 作者: V Vadim Petrochenkov

Implement empty struct with braces (RFC 218)

上级 cff04117
...@@ -1218,34 +1218,34 @@ fn print_expr_struct(&mut self, ...@@ -1218,34 +1218,34 @@ fn print_expr_struct(&mut self,
fields: &[hir::Field], fields: &[hir::Field],
wth: &Option<P<hir::Expr>>) -> io::Result<()> { wth: &Option<P<hir::Expr>>) -> io::Result<()> {
try!(self.print_path(path, true, 0)); try!(self.print_path(path, true, 0));
if !(fields.is_empty() && wth.is_none()) { try!(word(&mut self.s, "{"));
try!(word(&mut self.s, "{")); try!(self.commasep_cmnt(
try!(self.commasep_cmnt( Consistent,
Consistent, &fields[..],
&fields[..], |s, field| {
|s, field| { try!(s.ibox(indent_unit));
try!(s.ibox(indent_unit)); try!(s.print_ident(field.ident.node));
try!(s.print_ident(field.ident.node)); try!(s.word_space(":"));
try!(s.word_space(":")); try!(s.print_expr(&*field.expr));
try!(s.print_expr(&*field.expr)); s.end()
s.end() },
}, |f| f.span));
|f| f.span)); match *wth {
match *wth { Some(ref expr) => {
Some(ref expr) => { try!(self.ibox(indent_unit));
try!(self.ibox(indent_unit)); if !fields.is_empty() {
if !fields.is_empty() { try!(word(&mut self.s, ","));
try!(word(&mut self.s, ",")); try!(space(&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!(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(()) Ok(())
} }
......
...@@ -1473,14 +1473,14 @@ pub fn def_struct_variant(&self, ...@@ -1473,14 +1473,14 @@ pub fn def_struct_variant(&self,
_ => return None _ => 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)) Some((adt, variant))
} else { } else {
None None
} }
} }
pub fn write_nil(&self, node_id: ast::NodeId) { pub fn write_nil(&self, node_id: ast::NodeId) {
self.write_ty(node_id, self.tcx().mk_nil()); self.write_ty(node_id, self.tcx().mk_nil());
} }
......
...@@ -2231,14 +2231,6 @@ pub fn parse_bottom_expr(&mut self) -> PResult<P<Expr>> { ...@@ -2231,14 +2231,6 @@ pub fn parse_bottom_expr(&mut self) -> PResult<P<Expr>> {
&[token::CloseDelim(token::Brace)])); &[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; hi = self.span.hi;
try!(self.expect(&token::CloseDelim(token::Brace))); try!(self.expect(&token::CloseDelim(token::Brace)));
ex = ExprStruct(pth, fields, base); ex = ExprStruct(pth, fields, base);
...@@ -4713,14 +4705,14 @@ fn parse_item_struct(&mut self) -> PResult<ItemInfo> { ...@@ -4713,14 +4705,14 @@ fn parse_item_struct(&mut self) -> PResult<ItemInfo> {
(Vec::new(), Some(ast::DUMMY_NODE_ID)) (Vec::new(), Some(ast::DUMMY_NODE_ID))
} else { } else {
// If we see: `struct Foo<T> where T: Copy { ... }` // 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>;` // No `where` so: `struct Foo<T>;`
} else if try!(self.eat(&token::Semi) ){ } else if try!(self.eat(&token::Semi) ){
(Vec::new(), Some(ast::DUMMY_NODE_ID)) (Vec::new(), Some(ast::DUMMY_NODE_ID))
// Record-style struct definition // Record-style struct definition
} else if self.token == token::OpenDelim(token::Brace) { } 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) (fields, None)
// Tuple-style struct definition with optional where-clause. // Tuple-style struct definition with optional where-clause.
} else if self.token == token::OpenDelim(token::Paren) { } else if self.token == token::OpenDelim(token::Paren) {
...@@ -4740,20 +4732,13 @@ fn parse_item_struct(&mut self) -> PResult<ItemInfo> { ...@@ -4740,20 +4732,13 @@ fn parse_item_struct(&mut self) -> PResult<ItemInfo> {
None)) None))
} }
pub fn parse_record_struct_body(&mut self, pub fn parse_record_struct_body(&mut self) -> PResult<Vec<StructField>> {
class_name: &ast::Ident) -> PResult<Vec<StructField>> {
let mut fields = Vec::new(); let mut fields = Vec::new();
if try!(self.eat(&token::OpenDelim(token::Brace)) ){ if try!(self.eat(&token::OpenDelim(token::Brace)) ){
while self.token != token::CloseDelim(token::Brace) { while self.token != token::CloseDelim(token::Brace) {
fields.push(try!(self.parse_struct_decl_field(true))); 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()); try!(self.bump());
} else { } else {
let token_str = self.this_token_to_string(); let token_str = self.this_token_to_string();
......
...@@ -1855,34 +1855,34 @@ fn print_expr_struct(&mut self, ...@@ -1855,34 +1855,34 @@ fn print_expr_struct(&mut self,
fields: &[ast::Field], fields: &[ast::Field],
wth: &Option<P<ast::Expr>>) -> io::Result<()> { wth: &Option<P<ast::Expr>>) -> io::Result<()> {
try!(self.print_path(path, true, 0)); try!(self.print_path(path, true, 0));
if !(fields.is_empty() && wth.is_none()) { try!(word(&mut self.s, "{"));
try!(word(&mut self.s, "{")); try!(self.commasep_cmnt(
try!(self.commasep_cmnt( Consistent,
Consistent, &fields[..],
&fields[..], |s, field| {
|s, field| { try!(s.ibox(indent_unit));
try!(s.ibox(indent_unit)); try!(s.print_ident(field.ident.node));
try!(s.print_ident(field.ident.node)); try!(s.word_space(":"));
try!(s.word_space(":")); try!(s.print_expr(&*field.expr));
try!(s.print_expr(&*field.expr)); s.end()
s.end() },
}, |f| f.span));
|f| f.span)); match *wth {
match *wth { Some(ref expr) => {
Some(ref expr) => { try!(self.ibox(indent_unit));
try!(self.ibox(indent_unit)); if !fields.is_empty() {
if !fields.is_empty() { try!(word(&mut self.s, ","));
try!(word(&mut self.s, ",")); try!(space(&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!(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(()) Ok(())
} }
......
// 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 // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
...@@ -8,13 +8,10 @@ ...@@ -8,13 +8,10 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // 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() { fn main() {
let _end_stmt = Foo { }; let e = Empty; //~ ERROR `Empty` is the name of a struct or struct variant
//~^ ERROR: structure literal must either have at least one field
} }
fn main() {}
// 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 // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
...@@ -8,13 +8,17 @@ ...@@ -8,13 +8,17 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // 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() { struct Empty {}
let _mid_tuple = (Foo { }, 2);
//~^ ERROR: structure literal must either have at least one field 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`
}
}
...@@ -22,8 +22,8 @@ fn main() { ...@@ -22,8 +22,8 @@ fn main() {
let Foo { .. } = x; //~ ERROR `Foo` does not name a struct let Foo { .. } = x; //~ ERROR `Foo` does not name a struct
let x = Bar; let x = Bar;
Bar { ..x }; //~ ERROR `Bar` does not name a structure Bar { ..x };
let Bar { .. } = x; //~ ERROR `Bar` does not name a struct let Bar { .. } = x;
match Enum::Bar { match Enum::Bar {
Enum::Bar { .. } //~ ERROR `Enum::Bar` does not name a struct Enum::Bar { .. } //~ ERROR `Enum::Bar` does not name a struct
......
// 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() {}
// 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 // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
...@@ -8,13 +8,24 @@ ...@@ -8,13 +8,24 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// compile-flags: -Z parse-only // Empty struct defined with braces add names into type namespace
// Empty struct defined without braces add names into both type and value namespaces
struct Foo; struct Empty1 {}
struct Empty2;
fn h4() { fn main() {
let _end_of_tuple = (3, Foo { }); let e1: Empty1 = Empty1 {};
//~^ ERROR: structure literal must either have at least one field let e2: Empty2 = Empty2 {};
} let e2: Empty2 = Empty2;
fn main() {} match e1 {
Empty1 {} => ()
}
match e2 {
Empty2 {} => ()
}
match e2 {
Empty2 => ()
}
}
// 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 // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
...@@ -8,9 +8,13 @@ ...@@ -8,9 +8,13 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// compile-flags: -Z parse-only //`#[cfg]` on struct field permits empty unusable struct
struct Foo {} struct S {
//~^ ERROR: unit-like struct definition should be written as `struct Foo;` #[cfg(untrue)]
a: int,
}
fn main() {} fn main() {
let s = S {};
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册