Remove restrictions from tuple structs/variants
Hard errors are turned into feature gates
This commit is contained in:
parent
f55ac6944a
commit
59be332a1b
@ -197,27 +197,6 @@ impl<'a> Visitor for AstValidator<'a> {
|
||||
visit::walk_foreign_item(self, fi)
|
||||
}
|
||||
|
||||
fn visit_variant_data(&mut self,
|
||||
vdata: &VariantData,
|
||||
_: Ident,
|
||||
_: &Generics,
|
||||
_: NodeId,
|
||||
span: Span) {
|
||||
if vdata.fields().is_empty() {
|
||||
if vdata.is_tuple() {
|
||||
self.err_handler()
|
||||
.struct_span_err(span,
|
||||
"empty tuple structs and enum variants are not allowed, use \
|
||||
unit structs and enum variants instead")
|
||||
.span_help(span,
|
||||
"remove trailing `()` to make a unit struct or unit enum variant")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
visit::walk_struct_def(self, vdata)
|
||||
}
|
||||
|
||||
fn visit_vis(&mut self, vis: &Visibility) {
|
||||
match *vis {
|
||||
Visibility::Restricted { ref path, .. } => {
|
||||
|
@ -116,6 +116,7 @@ use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::codemap::{self, Spanned};
|
||||
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
||||
use syntax::parse::token::{self, InternedString, keywords};
|
||||
use syntax::ptr::P;
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
@ -1700,7 +1701,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
node_id: ast::NodeId)
|
||||
-> Ty<'tcx> {
|
||||
debug!("instantiate_type_path(did={:?}, path={:?})", did, path);
|
||||
let type_scheme = self.tcx.lookup_item_type(did);
|
||||
let mut type_scheme = self.tcx.lookup_item_type(did);
|
||||
if type_scheme.ty.is_fn() {
|
||||
// Tuple variants have fn type even in type namespace, extract true variant type from it
|
||||
let fn_ret = self.tcx.no_late_bound_regions(&type_scheme.ty.fn_ret()).unwrap().unwrap();
|
||||
type_scheme = ty::TypeScheme { ty: fn_ret, generics: type_scheme.generics }
|
||||
}
|
||||
let type_predicates = self.tcx.lookup_predicates(did);
|
||||
let substs = AstConv::ast_path_substs_for_ty(self, self,
|
||||
path.span,
|
||||
@ -3244,19 +3250,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
_ => None
|
||||
};
|
||||
if variant.is_none() || variant.unwrap().kind == ty::VariantKind::Tuple {
|
||||
// Reject tuple structs for now, braced and unit structs are allowed.
|
||||
|
||||
if let Some(variant) = variant {
|
||||
if variant.kind == ty::VariantKind::Tuple &&
|
||||
!self.tcx.sess.features.borrow().relaxed_adts {
|
||||
emit_feature_err(&self.tcx.sess.parse_sess.span_diagnostic,
|
||||
"relaxed_adts", span, GateIssue::Language,
|
||||
"tuple structs and variants in struct patterns are unstable");
|
||||
}
|
||||
let ty = self.instantiate_type_path(def.def_id(), path, node_id);
|
||||
Some((variant, ty))
|
||||
} else {
|
||||
struct_span_err!(self.tcx.sess, path.span, E0071,
|
||||
"`{}` does not name a struct or a struct variant",
|
||||
pprust::path_to_string(path))
|
||||
.span_label(path.span, &format!("not a struct"))
|
||||
.emit();
|
||||
|
||||
return None;
|
||||
None
|
||||
}
|
||||
|
||||
let ty = self.instantiate_type_path(def.def_id(), path, node_id);
|
||||
Some((variant.unwrap(), ty))
|
||||
}
|
||||
|
||||
fn check_expr_struct(&self,
|
||||
|
@ -280,7 +280,11 @@ declare_features! (
|
||||
(active, dotdot_in_tuple_patterns, "1.10.0", Some(33627)),
|
||||
|
||||
// Allows `impl Trait` in function return types.
|
||||
(active, conservative_impl_trait, "1.12.0", Some(34511))
|
||||
(active, conservative_impl_trait, "1.12.0", Some(34511)),
|
||||
|
||||
// Allows tuple structs and variants in more contexts,
|
||||
// Permits numeric fields in struct expressions and patterns.
|
||||
(active, relaxed_adts, "1.12.0", Some(35626))
|
||||
);
|
||||
|
||||
declare_features! (
|
||||
@ -1022,9 +1026,8 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
|
||||
}
|
||||
PatKind::TupleStruct(_, ref fields, ddpos)
|
||||
if ddpos.is_none() && fields.is_empty() => {
|
||||
self.context.span_handler.struct_span_err(pattern.span,
|
||||
"nullary enum variants are written with \
|
||||
no trailing `( )`").emit();
|
||||
gate_feature_post!(&self, relaxed_adts, pattern.span,
|
||||
"empty tuple structs patterns are unstable");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -1107,6 +1110,19 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
|
||||
visit::walk_impl_item(self, ii);
|
||||
}
|
||||
|
||||
fn visit_variant_data(&mut self, vdata: &ast::VariantData, _: ast::Ident,
|
||||
_: &ast::Generics, _: NodeId, span: Span) {
|
||||
if vdata.fields().is_empty() {
|
||||
if vdata.is_tuple() {
|
||||
gate_feature_post!(&self, relaxed_adts, span,
|
||||
"empty tuple structs and enum variants are unstable, \
|
||||
use unit structs and enum variants instead");
|
||||
}
|
||||
}
|
||||
|
||||
visit::walk_struct_def(self, vdata)
|
||||
}
|
||||
|
||||
fn visit_vis(&mut self, vis: &ast::Visibility) {
|
||||
let span = match *vis {
|
||||
ast::Visibility::Crate(span) => span,
|
||||
|
@ -8,11 +8,11 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
enum Foo { FirstValue(i32) }
|
||||
enum Foo {}
|
||||
|
||||
fn main() {
|
||||
let u = Foo::FirstValue { value: 0 };
|
||||
//~^ ERROR `Foo::FirstValue` does not name a struct or a struct variant [E0071]
|
||||
let u = Foo { value: 0 };
|
||||
//~^ ERROR `Foo` does not name a struct or a struct variant [E0071]
|
||||
//~| NOTE not a struct
|
||||
|
||||
let t = u32 { value: 4 };
|
||||
|
@ -8,10 +8,14 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(relaxed_adts)]
|
||||
|
||||
pub struct XEmpty1 {}
|
||||
pub struct XEmpty2;
|
||||
pub struct XEmpty6();
|
||||
|
||||
pub enum XE {
|
||||
XEmpty3 {},
|
||||
XEmpty4,
|
||||
XEmpty5(),
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
// aux-build:empty-struct.rs
|
||||
|
||||
#![feature(relaxed_adts)]
|
||||
|
||||
extern crate empty_struct;
|
||||
use empty_struct::*;
|
||||
|
||||
@ -21,13 +23,12 @@ fn main() {
|
||||
let e1 = Empty1 {};
|
||||
let xe1 = XEmpty1 {};
|
||||
|
||||
// Rejected by parser as yet
|
||||
// match e1 {
|
||||
// Empty1() => () // ERROR unresolved enum variant, struct or const `Empty1`
|
||||
// }
|
||||
// match xe1 {
|
||||
// XEmpty1() => () // ERROR unresolved enum variant, struct or const `XEmpty1`
|
||||
// }
|
||||
match e1 {
|
||||
Empty1() => () //~ ERROR unresolved variant or struct `Empty1`
|
||||
}
|
||||
match xe1 {
|
||||
XEmpty1() => () //~ ERROR unresolved variant or struct `XEmpty1`
|
||||
}
|
||||
match e1 {
|
||||
Empty1(..) => () //~ ERROR unresolved variant or struct `Empty1`
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
// aux-build:empty-struct.rs
|
||||
|
||||
#![feature(relaxed_adts)]
|
||||
|
||||
extern crate empty_struct;
|
||||
use empty_struct::*;
|
||||
|
||||
@ -23,13 +25,12 @@ fn main() {
|
||||
let e3 = E::Empty3 {};
|
||||
let xe3 = XE::XEmpty3 {};
|
||||
|
||||
// Rejected by parser as yet
|
||||
// match e3 {
|
||||
// E::Empty3() => () // ERROR `E::Empty3` does not name a tuple variant or a tuple struct
|
||||
// }
|
||||
// match xe3 {
|
||||
// E::Empty3() => () // ERROR `XE::XEmpty3` does not name a tuple variant or a tuple struct
|
||||
// }
|
||||
match e3 {
|
||||
E::Empty3() => () //~ ERROR `E::Empty3` does not name a tuple variant or a tuple struct
|
||||
}
|
||||
match xe3 {
|
||||
XE::XEmpty3() => () //~ ERROR `XE::XEmpty3` does not name a tuple variant or a tuple struct
|
||||
}
|
||||
match e3 {
|
||||
E::Empty3(..) => () //~ ERROR `E::Empty3` does not name a tuple variant or a tuple struct
|
||||
}
|
||||
|
47
src/test/compile-fail/empty-struct-tuple-pat.rs
Normal file
47
src/test/compile-fail/empty-struct-tuple-pat.rs
Normal file
@ -0,0 +1,47 @@
|
||||
// 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
|
||||
|
||||
// aux-build:empty-struct.rs
|
||||
|
||||
#![feature(relaxed_adts)]
|
||||
|
||||
extern crate empty_struct;
|
||||
use empty_struct::*;
|
||||
|
||||
struct Empty2();
|
||||
|
||||
enum E {
|
||||
Empty4()
|
||||
}
|
||||
|
||||
// remove attribute after warning cycle and promoting warnings to errors
|
||||
fn main() {
|
||||
let e2 = Empty2();
|
||||
let e4 = E::Empty4();
|
||||
let xe6 = XEmpty6();
|
||||
let xe5 = XE::XEmpty5();
|
||||
|
||||
match e2 {
|
||||
Empty2 => () //~ ERROR `Empty2` does not name a unit variant, unit struct or a constant
|
||||
}
|
||||
match xe6 {
|
||||
XEmpty6 => () //~ ERROR `XEmpty6` does not name a unit variant, unit struct or a constant
|
||||
}
|
||||
|
||||
match e4 {
|
||||
E::Empty4 => () //~ ERROR `E::Empty4` does not name a unit variant, unit struct or a
|
||||
}
|
||||
match xe5 {
|
||||
XE::XEmpty5 => (), //~ ERROR `XE::XEmpty5` does not name a unit variant, unit struct or a
|
||||
_ => {},
|
||||
}
|
||||
}
|
@ -12,6 +12,8 @@
|
||||
|
||||
// aux-build:empty-struct.rs
|
||||
|
||||
#![feature(relaxed_adts)]
|
||||
|
||||
extern crate empty_struct;
|
||||
use empty_struct::*;
|
||||
|
||||
@ -28,13 +30,6 @@ fn main() {
|
||||
let xe2 = XEmpty2;
|
||||
let xe4 = XE::XEmpty4;
|
||||
|
||||
// Rejected by parser as yet
|
||||
// match e2 {
|
||||
// Empty2() => () // ERROR `Empty2` does not name a tuple variant or a tuple struct
|
||||
// }
|
||||
// match xe2 {
|
||||
// XEmpty2() => () // ERROR `XEmpty2` does not name a tuple variant or a tuple struct
|
||||
// }
|
||||
match e2 {
|
||||
Empty2(..) => () //~ ERROR `Empty2` does not name a tuple variant or a tuple struct
|
||||
//~^ WARNING hard error
|
||||
@ -43,14 +38,7 @@ fn main() {
|
||||
XEmpty2(..) => () //~ ERROR `XEmpty2` does not name a tuple variant or a tuple struct
|
||||
//~^ WARNING hard error
|
||||
}
|
||||
// Rejected by parser as yet
|
||||
// match e4 {
|
||||
// E::Empty4() => () // ERROR `E::Empty4` does not name a tuple variant or a tuple struct
|
||||
// }
|
||||
// match xe4 {
|
||||
// XE::XEmpty4() => (), // ERROR `XE::XEmpty4` does not name a tuple variant or a tuple
|
||||
// _ => {},
|
||||
// }
|
||||
|
||||
match e4 {
|
||||
E::Empty4(..) => () //~ ERROR `E::Empty4` does not name a tuple variant or a tuple struct
|
||||
//~^ WARNING hard error
|
47
src/test/compile-fail/empty-struct-unit-pat-2.rs
Normal file
47
src/test/compile-fail/empty-struct-unit-pat-2.rs
Normal file
@ -0,0 +1,47 @@
|
||||
// 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
|
||||
|
||||
// aux-build:empty-struct.rs
|
||||
|
||||
#![feature(relaxed_adts)]
|
||||
|
||||
extern crate empty_struct;
|
||||
use empty_struct::*;
|
||||
|
||||
struct Empty2;
|
||||
|
||||
enum E {
|
||||
Empty4
|
||||
}
|
||||
|
||||
// remove attribute after warning cycle and promoting warnings to errors
|
||||
fn main() {
|
||||
let e2 = Empty2;
|
||||
let e4 = E::Empty4;
|
||||
let xe2 = XEmpty2;
|
||||
let xe4 = XE::XEmpty4;
|
||||
|
||||
match e2 {
|
||||
Empty2() => () //~ ERROR `Empty2` does not name a tuple variant or a tuple struct
|
||||
}
|
||||
match xe2 {
|
||||
XEmpty2() => () //~ ERROR `XEmpty2` does not name a tuple variant or a tuple struct
|
||||
}
|
||||
|
||||
match e4 {
|
||||
E::Empty4() => () //~ ERROR `E::Empty4` does not name a tuple variant or a tuple struct
|
||||
}
|
||||
match xe4 {
|
||||
XE::XEmpty4() => (), //~ ERROR `XE::XEmpty4` does not name a tuple variant or a tuple
|
||||
_ => {},
|
||||
}
|
||||
}
|
27
src/test/compile-fail/feature-gate-relaxed-adts-2.rs
Normal file
27
src/test/compile-fail/feature-gate-relaxed-adts-2.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2016 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 Z(u8, u8);
|
||||
|
||||
enum E {
|
||||
U(u8, u8),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match Z(0, 1) {
|
||||
Z{..} => {} //~ ERROR tuple structs and variants in struct patterns are unstable
|
||||
}
|
||||
match E::U(0, 1) {
|
||||
E::U{..} => {} //~ ERROR tuple structs and variants in struct patterns are unstable
|
||||
}
|
||||
|
||||
let z1 = Z(0, 1);
|
||||
let z2 = Z { ..z1 }; //~ ERROR tuple structs and variants in struct patterns are unstable
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
@ -8,16 +8,19 @@
|
||||
// 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 define an empty braced struct
|
||||
|
||||
struct Empty1 {}
|
||||
struct Empty2;
|
||||
struct S(); //~ ERROR empty tuple structs and enum variants are unstable
|
||||
struct Z(u8, u8);
|
||||
|
||||
enum E {
|
||||
Empty4 {},
|
||||
Empty5,
|
||||
V(), //~ ERROR empty tuple structs and enum variants are unstable
|
||||
U(u8, u8),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match S() {
|
||||
S() => {} //~ ERROR empty tuple structs patterns are unstable
|
||||
}
|
||||
match E::V() {
|
||||
E::V() => {} //~ ERROR empty tuple structs patterns are unstable
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// For style and consistency reasons, non-parametrized enum variants must
|
||||
// be used simply as `ident` instead of `ident ()`.
|
||||
// This test-case covers enum declaration.
|
||||
|
||||
enum Foo {
|
||||
Bar(), //~ ERROR empty tuple structs and enum variants are not allowed
|
||||
//~^ HELP remove trailing `()` to make a unit struct or unit enum variant
|
||||
Baz(), //~ ERROR empty tuple structs and enum variants are not allowed
|
||||
//~^ HELP remove trailing `()` to make a unit struct or unit enum variant
|
||||
Bazar
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{}", match Bar { Bar => 1, Baz => 2, Bazar => 3 }) //~ ERROR unresolved name `Bar`
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
// Copyright 2014 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 continue-parse-after-error
|
||||
|
||||
// For style and consistency reasons, non-parametrized enum variants must
|
||||
// be used simply as `ident` instead of `ident ()`.
|
||||
// This test-case covers enum matching.
|
||||
|
||||
enum Foo {
|
||||
Bar,
|
||||
Baz,
|
||||
Bazar
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{}", match Bar {
|
||||
Bar() => 1, //~ ERROR nullary enum variants are written with no trailing `( )`
|
||||
Baz() => 2, //~ ERROR nullary enum variants are written with no trailing `( )`
|
||||
Bazar => 3
|
||||
})
|
||||
}
|
@ -8,13 +8,13 @@
|
||||
// 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
|
||||
struct TS ( //~ ERROR empty tuple structs and enum variants are unstable
|
||||
#[cfg(untrue)]
|
||||
i32,
|
||||
);
|
||||
|
||||
enum E {
|
||||
TV ( //~ ERROR empty tuple structs and enum variants are not allowed
|
||||
TV ( //~ ERROR empty tuple structs and enum variants are unstable
|
||||
#[cfg(untrue)]
|
||||
i32,
|
||||
)
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(relaxed_adts)]
|
||||
|
||||
enum MyOption<T> {
|
||||
MySome(T),
|
||||
MyNone,
|
||||
@ -16,7 +18,8 @@ enum MyOption<T> {
|
||||
fn main() {
|
||||
match MyOption::MySome(42) {
|
||||
MyOption::MySome { x: 42 } => (),
|
||||
//~^ ERROR `MyOption::MySome` does not name a struct or a struct variant
|
||||
//~^ ERROR struct `MyOption::MySome` does not have a field named `x`
|
||||
//~| ERROR pattern does not mention field `0`
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -1,34 +0,0 @@
|
||||
// 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 Foo(u32);
|
||||
struct Bar;
|
||||
|
||||
enum Enum {
|
||||
Foo(u32),
|
||||
Bar
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = Foo(1);
|
||||
Foo { ..x }; //~ ERROR `Foo` does not name a struct or a struct variant
|
||||
let Foo { .. } = x; //~ ERROR `Foo` does not name a struct
|
||||
|
||||
let x = Bar;
|
||||
Bar { ..x };
|
||||
let Bar { .. } = x;
|
||||
|
||||
match Enum::Bar {
|
||||
Enum::Bar { .. }
|
||||
=> {}
|
||||
Enum::Foo { .. } //~ ERROR `Enum::Foo` does not name a struct
|
||||
=> {}
|
||||
}
|
||||
}
|
@ -8,8 +8,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(relaxed_adts)]
|
||||
|
||||
struct NonCopyable(());
|
||||
|
||||
fn main() {
|
||||
let z = NonCopyable{ p: () }; //~ ERROR `NonCopyable` does not name a struct or a struct variant
|
||||
let z = NonCopyable{ p: () }; //~ ERROR structure `NonCopyable` has no field named `p`
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
// Copyright 2014 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 Foo(); //~ ERROR empty tuple structs and enum variants are not allowed
|
||||
|
||||
fn main() {}
|
@ -8,10 +8,14 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(relaxed_adts)]
|
||||
|
||||
pub struct XEmpty1 {}
|
||||
pub struct XEmpty2;
|
||||
pub struct XEmpty7();
|
||||
|
||||
pub enum XE {
|
||||
XEmpty3 {},
|
||||
XEmpty4,
|
||||
XEmpty6(),
|
||||
}
|
||||
|
@ -1,46 +0,0 @@
|
||||
// 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 {};
|
||||
let e2: Empty2 = Empty2;
|
||||
let e5: E = E::Empty5 {};
|
||||
let e5: E = E::Empty5;
|
||||
|
||||
match e2 {
|
||||
Empty2 {} => {}
|
||||
}
|
||||
match e2 {
|
||||
Empty2 => {}
|
||||
}
|
||||
match e2 {
|
||||
Empty2 { .. } => {}
|
||||
}
|
||||
match e5 {
|
||||
E::Empty5 {} => {}
|
||||
}
|
||||
match e5 {
|
||||
E::Empty5 => {}
|
||||
}
|
||||
match e5 {
|
||||
E::Empty5 { .. } => {}
|
||||
}
|
||||
|
||||
let e22 = Empty2 { ..e2 };
|
||||
}
|
@ -13,11 +13,14 @@
|
||||
|
||||
// aux-build:empty-struct.rs
|
||||
|
||||
#![feature(relaxed_adts)]
|
||||
|
||||
extern crate empty_struct;
|
||||
use empty_struct::*;
|
||||
|
||||
struct Empty1 {}
|
||||
struct Empty2;
|
||||
struct Empty7();
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct Empty3 {}
|
||||
@ -27,6 +30,7 @@ const Empty3: Empty3 = Empty3 {};
|
||||
enum E {
|
||||
Empty4 {},
|
||||
Empty5,
|
||||
Empty6(),
|
||||
}
|
||||
|
||||
fn local() {
|
||||
@ -38,6 +42,12 @@ fn local() {
|
||||
let e4: E = E::Empty4 {};
|
||||
let e5: E = E::Empty5 {};
|
||||
let e5: E = E::Empty5;
|
||||
let e6: E = E::Empty6 {};
|
||||
let e6: E = E::Empty6();
|
||||
let ctor6: fn() -> E = E::Empty6;
|
||||
let e7: Empty7 = Empty7 {};
|
||||
let e7: Empty7 = Empty7();
|
||||
let ctor7: fn() -> Empty7 = Empty7;
|
||||
|
||||
match e1 {
|
||||
Empty1 {} => {}
|
||||
@ -56,6 +66,13 @@ fn local() {
|
||||
E::Empty5 {} => {}
|
||||
_ => {}
|
||||
}
|
||||
match e6 {
|
||||
E::Empty6 {} => {}
|
||||
_ => {}
|
||||
}
|
||||
match e7 {
|
||||
Empty7 {} => {}
|
||||
}
|
||||
|
||||
match e1 {
|
||||
Empty1 { .. } => {}
|
||||
@ -74,6 +91,13 @@ fn local() {
|
||||
E::Empty5 { .. } => {}
|
||||
_ => {}
|
||||
}
|
||||
match e6 {
|
||||
E::Empty6 { .. } => {}
|
||||
_ => {}
|
||||
}
|
||||
match e7 {
|
||||
Empty7 { .. } => {}
|
||||
}
|
||||
|
||||
match e2 {
|
||||
Empty2 => {}
|
||||
@ -85,10 +109,25 @@ fn local() {
|
||||
E::Empty5 => {}
|
||||
_ => {}
|
||||
}
|
||||
match e6 {
|
||||
E::Empty6() => {}
|
||||
_ => {}
|
||||
}
|
||||
match e6 {
|
||||
E::Empty6(..) => {}
|
||||
_ => {}
|
||||
}
|
||||
match e7 {
|
||||
Empty7() => {}
|
||||
}
|
||||
match e7 {
|
||||
Empty7(..) => {}
|
||||
}
|
||||
|
||||
let e11: Empty1 = Empty1 { ..e1 };
|
||||
let e22: Empty2 = Empty2 { ..e2 };
|
||||
let e33: Empty3 = Empty3 { ..e3 };
|
||||
let e77: Empty7 = Empty7 { ..e7 };
|
||||
}
|
||||
|
||||
fn xcrate() {
|
||||
@ -98,6 +137,12 @@ fn xcrate() {
|
||||
let e3: XE = XE::XEmpty3 {};
|
||||
let e4: XE = XE::XEmpty4 {};
|
||||
let e4: XE = XE::XEmpty4;
|
||||
let e6: XE = XE::XEmpty6 {};
|
||||
let e6: XE = XE::XEmpty6();
|
||||
let ctor6: fn() -> XE = XE::XEmpty6;
|
||||
let e7: XEmpty7 = XEmpty7 {};
|
||||
let e7: XEmpty7 = XEmpty7();
|
||||
let ctor7: fn() -> XEmpty7 = XEmpty7;
|
||||
|
||||
match e1 {
|
||||
XEmpty1 {} => {}
|
||||
@ -113,6 +158,13 @@ fn xcrate() {
|
||||
XE::XEmpty4 {} => {}
|
||||
_ => {}
|
||||
}
|
||||
match e6 {
|
||||
XE::XEmpty6 {} => {}
|
||||
_ => {}
|
||||
}
|
||||
match e7 {
|
||||
XEmpty7 {} => {}
|
||||
}
|
||||
|
||||
match e1 {
|
||||
XEmpty1 { .. } => {}
|
||||
@ -128,6 +180,13 @@ fn xcrate() {
|
||||
XE::XEmpty4 { .. } => {}
|
||||
_ => {}
|
||||
}
|
||||
match e6 {
|
||||
XE::XEmpty6 { .. } => {}
|
||||
_ => {}
|
||||
}
|
||||
match e7 {
|
||||
XEmpty7 { .. } => {}
|
||||
}
|
||||
|
||||
match e2 {
|
||||
XEmpty2 => {}
|
||||
@ -136,9 +195,24 @@ fn xcrate() {
|
||||
XE::XEmpty4 => {}
|
||||
_ => {}
|
||||
}
|
||||
match e6 {
|
||||
XE::XEmpty6() => {}
|
||||
_ => {}
|
||||
}
|
||||
match e6 {
|
||||
XE::XEmpty6(..) => {}
|
||||
_ => {}
|
||||
}
|
||||
match e7 {
|
||||
XEmpty7() => {}
|
||||
}
|
||||
match e7 {
|
||||
XEmpty7(..) => {}
|
||||
}
|
||||
|
||||
let e11: XEmpty1 = XEmpty1 { ..e1 };
|
||||
let e22: XEmpty2 = XEmpty2 { ..e2 };
|
||||
let e77: XEmpty7 = XEmpty7 { ..e7 };
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
Loading…
Reference in New Issue
Block a user