From 5fa6e857c9f43a69661ebca278c99155ee7d5db7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 10 Sep 2015 22:46:52 +0300 Subject: [PATCH 1/3] Implement empty struct with braces (RFC 218) --- src/librustc_front/print/pprust.rs | 50 +++++++++---------- src/librustc_typeck/check/mod.rs | 4 +- src/libsyntax/parse/parser.rs | 21 ++------ src/libsyntax/print/pprust.rs | 50 +++++++++---------- .../empty-struct-with-braces-1.rs} | 13 ++--- .../empty-struct-with-braces-2.rs} | 20 +++++--- src/test/compile-fail/issue-27831.rs | 4 +- src/test/parse-fail/struct-no-fields-4.rs | 20 -------- src/test/parse-fail/struct-no-fields-5.rs | 20 -------- src/test/run-pass/empty-struct-with-braces.rs | 31 ++++++++++++ .../issue-16819.rs} | 14 ++++-- 11 files changed, 114 insertions(+), 133 deletions(-) rename src/test/{parse-fail/struct-no-fields-2.rs => compile-fail/empty-struct-with-braces-1.rs} (62%) rename src/test/{parse-fail/struct-no-fields-3.rs => compile-fail/empty-struct-with-braces-2.rs} (52%) delete mode 100644 src/test/parse-fail/struct-no-fields-4.rs delete mode 100644 src/test/parse-fail/struct-no-fields-5.rs create mode 100644 src/test/run-pass/empty-struct-with-braces.rs rename src/test/{parse-fail/struct-no-fields.rs => run-pass/issue-16819.rs} (67%) 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/parse/parser.rs b/src/libsyntax/parse/parser.rs index b6650b6f94420..a7978babcb7e1 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 where T: Copy { ... }` - (try!(self.parse_record_struct_body(&class_name)), None) + (try!(self.parse_record_struct_body()), None) } // No `where` so: `struct Foo;` } 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> { + pub fn parse_record_struct_body(&mut self) -> PResult> { 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 b00ff85051c9a..1d22c83122e51 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>) -> 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 62% 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..bfe72856a2e17 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 similarity index 52% rename from src/test/parse-fail/struct-no-fields-3.rs rename to src/test/compile-fail/empty-struct-with-braces-2.rs index 8e72151ffe979..7e5a87fe1a44e 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 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-4.rs b/src/test/parse-fail/struct-no-fields-4.rs deleted file mode 100644 index 6e55baf06cedf..0000000000000 --- 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 or the MIT license -// , 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 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 or the MIT license -// , 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 0000000000000..a96c1e5b10c4b --- /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 or the MIT license +// , 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 similarity index 67% rename from src/test/parse-fail/struct-no-fields.rs rename to src/test/run-pass/issue-16819.rs index fa5065b763027..fb35ce33157d6 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 {}; +} From 605a4729481db73473dc37f09f840da6ec6173ab Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 11 Sep 2015 14:03:38 +0300 Subject: [PATCH 2/3] Add some more tests --- src/doc/reference.md | 13 +++++++++-- src/test/run-pass/empty-struct-with-braces.rs | 23 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index 18feebf3d5689..95a58686cf27e 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1178,11 +1178,20 @@ 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 structure implicitly defines a constant of +its type with the same name. For example: ``` struct Cookie; -let c = [Cookie, Cookie, Cookie, Cookie]; +let c = [Cookie, Cookie {}, Cookie, Cookie {}]; +``` + +is equivalent to + +``` +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 diff --git a/src/test/run-pass/empty-struct-with-braces.rs b/src/test/run-pass/empty-struct-with-braces.rs index a96c1e5b10c4b..6ed5f6954a017 100644 --- a/src/test/run-pass/empty-struct-with-braces.rs +++ b/src/test/run-pass/empty-struct-with-braces.rs @@ -13,11 +13,15 @@ struct Empty1 {} struct Empty2; +struct Empty3 {} +const Empty3: Empty3 = Empty3 {}; fn main() { let e1: Empty1 = Empty1 {}; let e2: Empty2 = Empty2 {}; let e2: Empty2 = Empty2; + let e3: Empty3 = Empty3 {}; + let e3: Empty3 = Empty3; match e1 { Empty1 {} => () @@ -28,4 +32,23 @@ fn main() { match e2 { Empty2 => () } + match e3 { + Empty3 {} => () + } + match e3 { + Empty3 => () + } + match e1 { + Empty1 { .. } => () + } + match e2 { + Empty2 { .. } => () + } + match e3 { + Empty3 { .. } => () + } + + let e11 = Empty1 { ..e1 }; + let e22 = Empty2 { ..e2 }; + let e33 = Empty3 { ..e3 }; } From 1eb42f1c784e999259b15f68c63040e1fafbe273 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 18 Sep 2015 13:36:45 +0300 Subject: [PATCH 3/3] Add feature gate --- src/doc/reference.md | 5 ++++- src/libsyntax/feature_gate.rs | 21 ++++++++++++++++++- .../empty-struct-with-braces-1.rs | 2 ++ .../empty-struct-with-braces-2.rs | 1 + .../empty-struct-with-braces-3.rs | 21 +++++++++++++++++++ src/test/run-pass/empty-struct-with-braces.rs | 2 ++ src/test/run-pass/issue-16819.rs | 2 ++ 7 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/empty-struct-with-braces-3.rs diff --git a/src/doc/reference.md b/src/doc/reference.md index 95a58686cf27e..83849574260e1 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1178,10 +1178,11 @@ 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 structure implicitly defines a constant of +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 {}]; ``` @@ -1189,6 +1190,7 @@ 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 {}]; @@ -2420,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/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, 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/test/compile-fail/empty-struct-with-braces-1.rs b/src/test/compile-fail/empty-struct-with-braces-1.rs index bfe72856a2e17..ad412259faa29 100644 --- a/src/test/compile-fail/empty-struct-with-braces-1.rs +++ b/src/test/compile-fail/empty-struct-with-braces-1.rs @@ -10,6 +10,8 @@ // Empty struct defined with braces shouldn't add names into value namespace +#![feature(braced_empty_structs)] + struct Empty {} fn main() { diff --git a/src/test/compile-fail/empty-struct-with-braces-2.rs b/src/test/compile-fail/empty-struct-with-braces-2.rs index 7e5a87fe1a44e..0e72e7dc44185 100644 --- a/src/test/compile-fail/empty-struct-with-braces-2.rs +++ b/src/test/compile-fail/empty-struct-with-braces-2.rs @@ -10,6 +10,7 @@ // Empty struct defined with braces shouldn't add names into value namespace +#![feature(braced_empty_structs)] #![deny(warnings)] struct Empty {} diff --git a/src/test/compile-fail/empty-struct-with-braces-3.rs b/src/test/compile-fail/empty-struct-with-braces-3.rs new file mode 100644 index 0000000000000..e6f20ba345ad3 --- /dev/null +++ b/src/test/compile-fail/empty-struct-with-braces-3.rs @@ -0,0 +1,21 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Feature gate test for empty struct with braces + +struct Empty {} //~ ERROR empty structs with braces are unstable + +fn main() { + let e = Empty {}; //~ ERROR empty structs with braces are unstable + + match e { + Empty {} => {} //~ ERROR empty structs with braces are unstable + } +} diff --git a/src/test/run-pass/empty-struct-with-braces.rs b/src/test/run-pass/empty-struct-with-braces.rs index 6ed5f6954a017..dc806acb980dd 100644 --- a/src/test/run-pass/empty-struct-with-braces.rs +++ b/src/test/run-pass/empty-struct-with-braces.rs @@ -11,6 +11,8 @@ // Empty struct defined with braces add names into type namespace // Empty struct defined without braces add names into both type and value namespaces +#![feature(braced_empty_structs)] + struct Empty1 {} struct Empty2; struct Empty3 {} diff --git a/src/test/run-pass/issue-16819.rs b/src/test/run-pass/issue-16819.rs index fb35ce33157d6..a9abb99696f59 100644 --- a/src/test/run-pass/issue-16819.rs +++ b/src/test/run-pass/issue-16819.rs @@ -10,6 +10,8 @@ //`#[cfg]` on struct field permits empty unusable struct +#![feature(braced_empty_structs)] + struct S { #[cfg(untrue)] a: int,