提交 8a12c191 编写于 作者: V Vadim Petrochenkov

Test and gate empty structures and variants better

上级 beda1f88
......@@ -2357,7 +2357,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.
* - `braced_empty_structs` - Allows use of empty structs and enum variants 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
......
......@@ -530,7 +530,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx hir::Pat,
let tcx = pcx.fcx.ccx.tcx;
let def = tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
let variant = match fcx.def_struct_variant(def) {
let variant = match fcx.def_struct_variant(def, path.span) {
Some((_, variant)) => variant,
None => {
let name = pprust::path_to_string(path);
......
......@@ -1464,7 +1464,8 @@ pub fn instantiate_type(&self,
/// Return the dict-like variant corresponding to a given `Def`.
pub fn def_struct_variant(&self,
def: def::Def)
def: def::Def,
span: Span)
-> Option<(ty::AdtDef<'tcx>, ty::VariantDef<'tcx>)>
{
let (adt, variant) = match def {
......@@ -1484,11 +1485,20 @@ pub fn def_struct_variant(&self,
};
let var_kind = variant.kind();
if var_kind == ty::VariantKind::Dict || var_kind == ty::VariantKind::Unit {
if var_kind == ty::VariantKind::Dict {
Some((adt, variant))
} else {
None
}
} else if var_kind == ty::VariantKind::Unit {
if !self.tcx().sess.features.borrow().braced_empty_structs {
self.tcx().sess.span_err(span, "empty structs and enum variants \
with braces are unstable");
fileline_help!(self.tcx().sess, span, "add #![feature(braced_empty_structs)] to \
the crate features to enable");
}
Some((adt, variant))
} else {
None
}
}
pub fn write_nil(&self, node_id: ast::NodeId) {
......@@ -3177,7 +3187,7 @@ fn check_expr_struct<'a, 'tcx>(fcx: &FnCtxt<'a,'tcx>,
// Find the relevant variant
let def = lookup_full_def(tcx, path.span, expr.id);
let (adt, variant) = match fcx.def_struct_variant(def) {
let (adt, variant) = match fcx.def_struct_variant(def, path.span) {
Some((adt, variant)) => (adt, variant),
None => {
span_err!(fcx.tcx().sess, path.span, E0071,
......
......@@ -196,7 +196,7 @@
// allow `#[unwind]`
("unwind_attributes", "1.4.0", None, Active),
// allow empty structs/enum variants with braces
// allow empty structs and enum variants with braces
("braced_empty_structs", "1.5.0", None, Active),
// allow overloading augmented assignment operations like `a += b`
......@@ -486,6 +486,7 @@ pub struct Features {
pub cfg_target_feature: bool,
pub cfg_target_vendor: bool,
pub augmented_assignments: bool,
pub braced_empty_structs: bool,
}
impl Features {
......@@ -516,6 +517,7 @@ pub fn new() -> Features {
cfg_target_feature: false,
cfg_target_vendor: false,
augmented_assignments: false,
braced_empty_structs: false,
}
}
}
......@@ -809,7 +811,7 @@ fn visit_item(&mut self, i: &ast::Item) {
}
}
ast::ItemStruct(ref def, _) => {
ast::ItemStruct(..) => {
if attr::contains_name(&i.attrs[..], "simd") {
self.gate_feature("simd", i.span,
"SIMD types are experimental and possibly buggy");
......@@ -828,10 +830,6 @@ fn visit_item(&mut self, i: &ast::Item) {
}
}
}
if def.fields.is_empty() && def.kind == ast::VariantKind::Dict {
self.gate_feature("braced_empty_structs", i.span,
"empty structs with braces are unstable");
}
}
ast::ItemDefaultImpl(..) => {
......@@ -859,6 +857,21 @@ fn visit_item(&mut self, i: &ast::Item) {
visit::walk_item(self, i);
}
fn visit_struct_def(&mut self, s: &'v ast::StructDef, _: ast::Ident,
_: &'v ast::Generics, _: ast::NodeId, span: Span) {
if s.fields.is_empty() {
if s.kind == ast::VariantKind::Dict {
self.gate_feature("braced_empty_structs", span,
"empty structs and enum variants with braces are unstable");
} else if s.kind == ast::VariantKind::Tuple {
self.context.span_handler.span_err(span, "empty tuple structs and enum variants \
are not allowed, use unit structs and \
enum variants instead");
}
}
visit::walk_struct_def(self, s)
}
fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs,
"link_name") {
......@@ -881,12 +894,6 @@ fn visit_expr(&mut self, e: &ast::Expr) {
"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);
......@@ -911,12 +918,6 @@ fn visit_pat(&mut self, pattern: &ast::Pat) {
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)
......@@ -1086,6 +1087,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
cfg_target_feature: cx.has_feature("cfg_target_feature"),
cfg_target_vendor: cx.has_feature("cfg_target_vendor"),
augmented_assignments: cx.has_feature("augmented_assignments"),
braced_empty_structs: cx.has_feature("braced_empty_structs"),
}
}
......
......@@ -4658,7 +4658,7 @@ fn parse_item_struct(&mut self) -> PResult<ItemInfo> {
(fields, VariantKind::Dict)
// Tuple-style struct definition with optional where-clause.
} else if self.token == token::OpenDelim(token::Paren) {
let fields = try!(self.parse_tuple_struct_body(class_name, &mut generics));
let fields = try!(self.parse_tuple_struct_body(&mut generics));
(fields, VariantKind::Tuple)
} else {
let token_str = self.this_token_to_string();
......@@ -4694,7 +4694,6 @@ pub fn parse_record_struct_body(&mut self) -> PResult<Vec<StructField>> {
}
pub fn parse_tuple_struct_body(&mut self,
class_name: ast::Ident,
generics: &mut ast::Generics)
-> PResult<Vec<StructField>> {
// This is the case where we find `struct Foo<T>(T) where T: Copy;`
......@@ -4715,12 +4714,6 @@ pub fn parse_tuple_struct_body(&mut self,
Ok(spanned(lo, p.span.hi, struct_field_))
}));
if fields.is_empty() {
return Err(self.fatal(&format!("unit-like struct definition should be \
written as `struct {};`",
class_name)));
}
generics.where_clause = try!(self.parse_where_clause());
try!(self.expect(&token::Semi));
Ok(fields)
......
// 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.
// Can't use empty braced struct as constant or constructor function
#![feature(braced_empty_structs)]
struct Empty1 {}
enum E {
Empty2 {}
}
fn main() {
let e1 = Empty1; //~ ERROR `Empty1` is the name of a struct or struct variant
let e1 = Empty1(); //~ ERROR `Empty1` is the name of a struct or struct variant
let e2 = E::Empty2; //~ ERROR `E::Empty2` is the name of a struct or struct variant
let e2 = E::Empty2(); //~ ERROR `E::Empty2` is the name of a struct or struct variant
}
......@@ -9,13 +9,15 @@
// except according to those terms.
// Feature gate test for empty struct with braces
// Can't define an empty braced struct
struct Empty {} //~ ERROR empty structs with braces are unstable
struct Empty1 {} //~ ERROR empty structs and enum variants with braces are unstable
struct Empty2;
fn main() {
let e = Empty {}; //~ ERROR empty structs with braces are unstable
enum E {
Empty4 {}, //~ ERROR empty structs and enum variants with braces are unstable
Empty5,
}
match e {
Empty {} => {} //~ ERROR empty structs with braces are unstable
}
fn main() {
}
// 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.
// Feature gate test for empty struct with braces
// Can't use braced expressions and patterns with structs defined without braces
struct Empty2;
enum E {
Empty5,
}
fn main() {
let e2: Empty2 = Empty2 {}; //~ ERROR empty structs and enum variants with braces are unstable
let e2: Empty2 = Empty2;
// Issue #28692
// let e5: E = E::Empty5 {}; // ERROR empty structs and enum variants with braces are unstable
let e5: E = E::Empty5;
match e2 {
Empty2 {} => {} //~ ERROR empty structs and enum variants with braces are unstable
}
match e2 {
Empty2 => {}
}
match e2 {
Empty2 { .. } => {} //~ ERROR empty structs and enum variants with braces are unstable
}
// Issue #28692
// match e5 {
// E::Empty5 {} => {} // ERROR empty structs and enum variants with braces are unstable
// }
match e5 {
E::Empty5 => {}
}
// Issue #28692
// match e5 {
// E::Empty5 { .. } => {} // ERROR empty structs and enum variants with braces are unstable
// }
let e22 = Empty2 { ..e2 }; //~ ERROR empty structs and enum variants with braces are unstable
}
......@@ -8,18 +8,26 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Empty struct defined with braces shouldn't add names into value namespace
// Can't use empty braced struct as constant pattern
#![feature(braced_empty_structs)]
#![deny(warnings)]
#![feature(braced_empty_structs)]
struct Empty {}
struct Empty1 {}
enum E {
Empty2 {}
}
fn main() {
let e = Empty {};
let e1 = Empty1 {};
let e2 = E::Empty2 {};
match e {
Empty => () //~ ERROR unused variable: `Empty`
//~^ ERROR variable `Empty` should have a snake case name such as `empty`
// Issue #28692
// match e1 {
// Empty1 => () // ERROR incorrect error
// }
match e2 {
E::Empty2 => () //~ ERROR `E::Empty2` does not name a non-struct variant or a tuple struct
}
}
// 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.
// Can't use empty braced struct as enum pattern
#![feature(braced_empty_structs)]
struct Empty1 {}
enum E {
Empty2 {}
}
fn main() {
let e1 = Empty1 {};
let e2 = E::Empty2 {};
// Rejected by parser as yet
// match e1 {
// Empty1() => () // ERROR unresolved enum variant, struct or const `Empty1`
// }
match e1 {
Empty1(..) => () //~ ERROR unresolved enum variant, struct or const `Empty1`
}
// Issue #28692
// match e2 {
// E::Empty2() => () // ERROR unresolved enum variant, struct or const `Empty2`
// }
// match e2 {
// E::Empty2(..) => () // ERROR unresolved enum variant, struct or const `Empty2`
// }
}
......@@ -8,12 +8,17 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Empty struct defined with braces shouldn't add names into value namespace
// Can't use unit struct as constructor function
#![feature(braced_empty_structs)]
struct Empty {}
struct Empty1;
enum E {
Empty2
}
fn main() {
let e = Empty; //~ ERROR `Empty` is the name of a struct or struct variant
let e1 = Empty1(); //~ ERROR expected function, found `Empty1`
let e2 = E::Empty2(); //~ ERROR expected function, found `E`
}
// 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.
// Can't use unit struct as enum pattern
#![feature(braced_empty_structs)]
FIXME //~ ERROR expected item, found `FIXME`
struct Empty1;
enum E {
Empty2
}
fn main() {
let e1 = Empty1;
let e2 = E::Empty2;
// Issue #28692
// match e1 {
// Empty1() => () // ERROR variable `Empty1` should have a snake case name
// }
// match e1 {
// Empty1(..) => () // ERROR variable `Empty1` should have a snake case name
// }
// match e2 {
// E::Empty2() => () // ERROR variable `Empty2` should have a snake case name
// }
// match e2 {
// E::Empty2(..) => () // ERROR variable `Empty2` should have a snake case name
// }
}
// 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.
struct TS ( //~ ERROR empty tuple structs and enum variants are not allowed
#[cfg(untrue)]
int,
);
fn main() {
let s = S;
}
......@@ -22,8 +22,8 @@ fn main() {
let Foo { .. } = x; //~ ERROR `Foo` does not name a struct
let x = Bar;
Bar { ..x };
let Bar { .. } = x;
Bar { ..x }; //~ ERROR empty structs and enum variants with braces are unstable
let Bar { .. } = x; //~ ERROR empty structs and enum variants with braces are unstable
match Enum::Bar {
Enum::Bar { .. } //~ ERROR `Enum::Bar` does not name a struct
......
......@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: -Z parse-only
struct Foo(); //~ ERROR unit-like struct definition should be written as `struct Foo;`
struct Foo(); //~ ERROR empty tuple structs and enum variants are not allowed
fn main() {}
......@@ -18,39 +18,71 @@ struct Empty1 {}
struct Empty3 {}
const Empty3: Empty3 = Empty3 {};
enum E {
Empty4 {},
Empty5,
}
fn main() {
let e1: Empty1 = Empty1 {};
let e2: Empty2 = Empty2 {};
let e2: Empty2 = Empty2;
let e3: Empty3 = Empty3 {};
let e3: Empty3 = Empty3;
let e4: E = E::Empty4 {};
// let e5: E = E::Empty5 {}; // Issue #28692
let e5: E = E::Empty5;
match e1 {
Empty1 {} => ()
}
match e2 {
Empty2 {} => ()
Empty1 {} => {}
}
match e2 {
Empty2 => ()
Empty2 {} => {}
}
match e3 {
Empty3 {} => ()
Empty3 {} => {}
}
match e3 {
Empty3 => ()
match e4 {
E::Empty4 {} => {}
_ => {}
}
// Issue #28692
// match e5 {
// E::Empty5 {} => {}
// _ => {}
// }
match e1 {
Empty1 { .. } => ()
Empty1 { .. } => {}
}
match e2 {
Empty2 { .. } => ()
Empty2 { .. } => {}
}
match e3 {
Empty3 { .. } => ()
Empty3 { .. } => {}
}
match e4 {
E::Empty4 { .. } => {}
_ => {}
}
// Issue #28692
// match e5 {
// E::Empty5 { .. } => {}
// _ => {}
// }
match e2 {
Empty2 => {}
}
match e3 {
Empty3 => {}
}
match e5 {
E::Empty5 => {}
_ => {}
}
let e11 = Empty1 { ..e1 };
let e22 = Empty2 { ..e2 };
let e33 = Empty3 { ..e3 };
let e11: Empty1 = Empty1 { ..e1 };
let e22: Empty2 = Empty2 { ..e2 };
let e33: Empty3 = Empty3 { ..e3 };
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册