diff options
| author | bors <bors@rust-lang.org> | 2016-09-03 07:48:06 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-09-03 07:48:06 -0700 |
| commit | d748fa6ecccf6f5b4c7ae4abee0a2d206b165de2 (patch) | |
| tree | 5ada2c11762533ba6c6f21a7593b015cb1a89912 /src/test/compile-fail | |
| parent | 01b35d82e51458870f61cf850b73479f253fcb54 (diff) | |
| parent | 436cfe56534b405786816d4bbcccd11ed7571981 (diff) | |
Auto merge of #36016 - petrochenkov:union, r=nikomatsakis
Implement untagged unions (RFC 1444)
cc https://github.com/rust-lang/rust/issues/32836
Notes:
- The RFC doesn't talk about `#[packed]` unions, this implementation supports them, packing changes union's alignment to 1 and removes trailing padding.
- The RFC doesn't talk about dynamically sized unions, this implementation doesn't support them and rejects them during wf-checking (similarly, dynamically sized enums are not supported as well).
- The lint for drop fields in unions can't work precisely before monomorphization, so it works pessimistically - non-`Copy` generic fields are reported, types not implementing `Drop` directly, but having non-trivial drop code are reported.
```
struct S(String); // Doesn't implement `Drop`
union U<T> {
a: S, // Reported
b: T, // Reported
}
```
- https://github.com/rust-lang/rust/pull/35764 was indeed helpful and landed timely, I didn't have to implement internal drop flags for unions.
- Unions are not permitted in constant patterns, because matching on union fields is unsafe, I didn't want unsafety checker to dig into all constants to uncover this possible unsafety.
- The RFC doesn't talk about `#[derive]`, generally trait impls cannot be derived for unions, but some of them can. I implemented only `#[derive(Copy)]` so far. In theory shallow `#[derive(Clone)]` can be derived as well if all union fields are `Copy`, I left it for later though, it requires changing how `Clone` impls are generated.
- Moving union fields is implemented as per https://github.com/rust-lang/rust/issues/32836#issuecomment-242511491.
- Testing strategy: union specific behavior is tested, sometimes very basically (e.g. debuginfo), behavior common for all ADTs (e.g. something like coherence
checks) is not generally tested.
r? @eddyb
Diffstat (limited to 'src/test/compile-fail')
32 files changed, 748 insertions, 22 deletions
diff --git a/src/test/compile-fail/attr-usage-repr.rs b/src/test/compile-fail/attr-usage-repr.rs index 9bad6a8389a..b07d3e2f906 100644 --- a/src/test/compile-fail/attr-usage-repr.rs +++ b/src/test/compile-fail/attr-usage-repr.rs @@ -11,7 +11,7 @@ #![allow(dead_code)] #![feature(repr_simd)] -#[repr(C)] //~ ERROR: attribute should be applied to struct or enum +#[repr(C)] //~ ERROR: attribute should be applied to struct, enum or union fn f() {} #[repr(C)] diff --git a/src/test/compile-fail/borrowck/borrowck-union-borrow-nested.rs b/src/test/compile-fail/borrowck/borrowck-union-borrow-nested.rs new file mode 100644 index 00000000000..19975d79b60 --- /dev/null +++ b/src/test/compile-fail/borrowck/borrowck-union-borrow-nested.rs @@ -0,0 +1,44 @@ +// 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. + +// ignore-tidy-linelength + +#![feature(untagged_unions)] + +#[derive(Clone, Copy)] +struct S { + a: u8, + b: u16, +} + +union U { + s: S, + c: u32, +} + +impl Clone for U { + fn clone(&self) -> Self { *self } +} +impl Copy for U {} + +fn main() { + unsafe { + { + let mut u = U { s: S { a: 0, b: 1 } }; + let ra = &mut u.s.a; + let b = u.s.b; // OK + } + { + let mut u = U { s: S { a: 0, b: 1 } }; + let ra = &mut u.s.a; + let b = u.c; //~ ERROR cannot use `u.c` because it was mutably borrowed + } + } +} diff --git a/src/test/compile-fail/borrowck/borrowck-union-borrow.rs b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs new file mode 100644 index 00000000000..e8989a3c2d4 --- /dev/null +++ b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs @@ -0,0 +1,97 @@ +// 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. + +// ignore-tidy-linelength + +#![feature(untagged_unions)] + +union U { + a: u8, + b: u64, +} + +impl Clone for U { + fn clone(&self) -> Self { *self } +} +impl Copy for U {} + +fn main() { + unsafe { + let mut u = U { b: 0 }; + // Imm borrow, same field + { + let ra = &u.a; + let ra2 = &u.a; // OK + } + { + let ra = &u.a; + let a = u.a; // OK + } + { + let ra = &u.a; + let rma = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable + } + { + let ra = &u.a; + u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed + } + // Imm borrow, other field + { + let ra = &u.a; + let rb = &u.b; // OK + } + { + let ra = &u.a; + let b = u.b; // OK + } + { + let ra = &u.a; + let rmb = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`) + } + { + let ra = &u.a; + u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed + } + // Mut borrow, same field + { + let rma = &mut u.a; + let ra = &u.a; //~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable + } + { + let ra = &mut u.a; + let a = u.a; //~ ERROR cannot use `u.a` because it was mutably borrowed + } + { + let rma = &mut u.a; + let rma2 = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable more than once at a time + } + { + let rma = &mut u.a; + u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed + } + // Mut borrow, other field + { + let rma = &mut u.a; + let rb = &u.b; //~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`) + } + { + let ra = &mut u.a; + let b = u.b; //~ ERROR cannot use `u.b` because it was mutably borrowed + } + { + let rma = &mut u.a; + let rmb2 = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time + } + { + let rma = &mut u.a; + u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed + } + } +} diff --git a/src/test/compile-fail/borrowck/borrowck-union-move-assign.rs b/src/test/compile-fail/borrowck/borrowck-union-move-assign.rs new file mode 100644 index 00000000000..d4d7bc6b0f7 --- /dev/null +++ b/src/test/compile-fail/borrowck/borrowck-union-move-assign.rs @@ -0,0 +1,42 @@ +// 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. + +#![feature(untagged_unions)] + +// Non-copy +struct A; +struct B; + +union U { + a: A, + b: B, +} + +fn main() { + unsafe { + { + let mut u = U { a: A }; + let a = u.a; + let a = u.a; //~ ERROR use of moved value: `u.a` + } + { + let mut u = U { a: A }; + let a = u.a; + u.a = A; + let a = u.a; // OK + } + { + let mut u = U { a: A }; + let a = u.a; + u.b = B; + let a = u.a; // OK + } + } +} diff --git a/src/test/compile-fail/borrowck/borrowck-union-move.rs b/src/test/compile-fail/borrowck/borrowck-union-move.rs new file mode 100644 index 00000000000..5320244cf43 --- /dev/null +++ b/src/test/compile-fail/borrowck/borrowck-union-move.rs @@ -0,0 +1,96 @@ +// 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. + +#![feature(untagged_unions)] + +#[derive(Clone, Copy)] +struct Copy; +struct NonCopy; + +union Unn { + n1: NonCopy, + n2: NonCopy, +} +union Ucc { + c1: Copy, + c2: Copy, +} +union Ucn { + c: Copy, + n: NonCopy, +} + +fn main() { + unsafe { + // 2 NonCopy + { + let mut u = Unn { n1: NonCopy }; + let a = u.n1; + let a = u.n1; //~ ERROR use of moved value: `u.n1` + } + { + let mut u = Unn { n1: NonCopy }; + let a = u.n1; + let a = u; //~ ERROR use of partially moved value: `u` + } + { + let mut u = Unn { n1: NonCopy }; + let a = u.n1; + let a = u.n2; //~ ERROR use of moved value: `u.n2` + } + // 2 Copy + { + let mut u = Ucc { c1: Copy }; + let a = u.c1; + let a = u.c1; // OK + } + { + let mut u = Ucc { c1: Copy }; + let a = u.c1; + let a = u; // OK + } + { + let mut u = Ucc { c1: Copy }; + let a = u.c1; + let a = u.c2; // OK + } + // 1 Copy, 1 NonCopy + { + let mut u = Ucn { c: Copy }; + let a = u.c; + let a = u.c; // OK + } + { + let mut u = Ucn { c: Copy }; + let a = u.n; + let a = u.n; //~ ERROR use of moved value: `u.n` + } + { + let mut u = Ucn { c: Copy }; + let a = u.n; + let a = u.c; //~ ERROR use of moved value: `u.c` + } + { + let mut u = Ucn { c: Copy }; + let a = u.c; + let a = u.n; // OK + } + { + let mut u = Ucn { c: Copy }; + let a = u.c; + let a = u; // OK + } + { + let mut u = Ucn { c: Copy }; + let a = u.n; + let a = u; //~ ERROR use of partially moved value: `u` + } + } +} diff --git a/src/test/compile-fail/borrowck/borrowck-union-uninitialized.rs b/src/test/compile-fail/borrowck/borrowck-union-uninitialized.rs new file mode 100644 index 00000000000..36e062f8464 --- /dev/null +++ b/src/test/compile-fail/borrowck/borrowck-union-uninitialized.rs @@ -0,0 +1,30 @@ +// 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. + +#![feature(untagged_unions)] + +struct S { + a: u8, +} + +union U { + a: u8, +} + +fn main() { + unsafe { + let mut s: S; + let mut u: U; + s.a = 0; + u.a = 0; + let sa = s.a; //~ ERROR use of possibly uninitialized variable: `s.a` + let ua = u.a; //~ ERROR use of possibly uninitialized variable: `u.a` + } +} diff --git a/src/test/compile-fail/deriving-non-type.rs b/src/test/compile-fail/deriving-non-type.rs index 5b215f3ccd9..84dd22435b8 100644 --- a/src/test/compile-fail/deriving-non-type.rs +++ b/src/test/compile-fail/deriving-non-type.rs @@ -12,29 +12,29 @@ struct S; -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs and enums +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions trait T { } -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs and enums +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions impl S { } -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs and enums +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions impl T for S { } -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs and enums +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions static s: usize = 0; -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs and enums +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions const c: usize = 0; -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs and enums +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions mod m { } -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs and enums +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions extern "C" { } -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs and enums +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions type A = usize; -#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs and enums +#[derive(PartialEq)] //~ ERROR: `derive` may only be applied to structs, enums and unions fn main() { } diff --git a/src/test/compile-fail/issue-17800.rs b/src/test/compile-fail/issue-17800.rs index 58d580a5c1a..d5f1614c14d 100644 --- a/src/test/compile-fail/issue-17800.rs +++ b/src/test/compile-fail/issue-17800.rs @@ -18,7 +18,7 @@ enum MyOption<T> { fn main() { match MyOption::MySome(42) { MyOption::MySome { x: 42 } => (), - //~^ ERROR struct `MyOption::MySome` does not have a field named `x` + //~^ ERROR variant `MyOption::MySome` does not have a field named `x` //~| ERROR pattern does not mention field `0` _ => (), } diff --git a/src/test/compile-fail/issue-19922.rs b/src/test/compile-fail/issue-19922.rs index e3ced302809..a8350fe0986 100644 --- a/src/test/compile-fail/issue-19922.rs +++ b/src/test/compile-fail/issue-19922.rs @@ -14,5 +14,5 @@ enum Homura { fn main() { let homura = Homura::Akemi { kaname: () }; - //~^ ERROR struct variant `Homura::Akemi` has no field named `kaname` + //~^ ERROR variant `Homura::Akemi` has no field named `kaname` } diff --git a/src/test/compile-fail/issue-31769.rs b/src/test/compile-fail/issue-31769.rs index 4b5df7ea53c..7f73d9076ec 100644 --- a/src/test/compile-fail/issue-31769.rs +++ b/src/test/compile-fail/issue-31769.rs @@ -10,5 +10,5 @@ fn main() { #[inline] struct Foo; //~ ERROR attribute should be applied to function - #[repr(C)] fn foo() {} //~ ERROR attribute should be applied to struct or enum + #[repr(C)] fn foo() {} //~ ERROR attribute should be applied to struct, enum or union } diff --git a/src/test/compile-fail/issue-4736.rs b/src/test/compile-fail/issue-4736.rs index a8a1b1482fc..c93e75042dd 100644 --- a/src/test/compile-fail/issue-4736.rs +++ b/src/test/compile-fail/issue-4736.rs @@ -13,5 +13,5 @@ struct NonCopyable(()); fn main() { - let z = NonCopyable{ p: () }; //~ ERROR structure `NonCopyable` has no field named `p` + let z = NonCopyable{ p: () }; //~ ERROR struct `NonCopyable` has no field named `p` } diff --git a/src/test/compile-fail/numeric-fields.rs b/src/test/compile-fail/numeric-fields.rs index 480d2dcdddd..c4aff9471b8 100644 --- a/src/test/compile-fail/numeric-fields.rs +++ b/src/test/compile-fail/numeric-fields.rs @@ -13,7 +13,7 @@ struct S(u8, u16); fn main() { - let s = S{0b1: 10, 0: 11}; //~ ERROR structure `S` has no field named `0b1` + let s = S{0b1: 10, 0: 11}; //~ ERROR struct `S` has no field named `0b1` match s { S{0: a, 0x1: b, ..} => {} //~ ERROR does not have a field named `0x1` } diff --git a/src/test/compile-fail/privacy/union-field-privacy-1.rs b/src/test/compile-fail/privacy/union-field-privacy-1.rs new file mode 100644 index 00000000000..4924fabafb0 --- /dev/null +++ b/src/test/compile-fail/privacy/union-field-privacy-1.rs @@ -0,0 +1,30 @@ +// 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. + +#![feature(pub_restricted)] +#![feature(untagged_unions)] + +mod m { + pub union U { + pub a: u8, + pub(super) b: u8, + c: u8, + } +} + +fn main() { + let u = m::U { a: 0 }; // OK + let u = m::U { b: 0 }; // OK + let u = m::U { c: 0 }; //~ ERROR field `c` of union `m::U` is private + + let m::U { a } = u; // OK + let m::U { b } = u; // OK + let m::U { c } = u; //~ ERROR field `c` of union `m::U` is private +} diff --git a/src/test/compile-fail/privacy/union-field-privacy-2.rs b/src/test/compile-fail/privacy/union-field-privacy-2.rs new file mode 100644 index 00000000000..7151538f412 --- /dev/null +++ b/src/test/compile-fail/privacy/union-field-privacy-2.rs @@ -0,0 +1,28 @@ +// 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. + +#![feature(pub_restricted)] +#![feature(untagged_unions)] + +mod m { + pub union U { + pub a: u8, + pub(super) b: u8, + c: u8, + } +} + +fn main() { + let u = m::U { a: 10 }; + + let a = u.a; // OK + let b = u.b; // OK + let c = u.c; //~ ERROR field `c` of struct `m::U` is private +} diff --git a/src/test/compile-fail/struct-fields-hints-no-dupe.rs b/src/test/compile-fail/struct-fields-hints-no-dupe.rs index 8df9ffd6cc7..5f1f8ca856f 100644 --- a/src/test/compile-fail/struct-fields-hints-no-dupe.rs +++ b/src/test/compile-fail/struct-fields-hints-no-dupe.rs @@ -17,7 +17,7 @@ struct A { fn main() { let a = A { foo : 5, - bar : 42,//~ ERROR structure `A` has no field named `bar` + bar : 42,//~ ERROR struct `A` has no field named `bar` //~^ HELP did you mean `barr`? car : 9, }; diff --git a/src/test/compile-fail/struct-fields-hints.rs b/src/test/compile-fail/struct-fields-hints.rs index 37001f1e60a..4ba1fd2f7bb 100644 --- a/src/test/compile-fail/struct-fields-hints.rs +++ b/src/test/compile-fail/struct-fields-hints.rs @@ -17,7 +17,7 @@ struct A { fn main() { let a = A { foo : 5, - bar : 42,//~ ERROR structure `A` has no field named `bar` + bar : 42,//~ ERROR struct `A` has no field named `bar` //~^ HELP did you mean `car`? }; } diff --git a/src/test/compile-fail/struct-fields-too-many.rs b/src/test/compile-fail/struct-fields-too-many.rs index 9244a9d4f9d..5d16573f2f1 100644 --- a/src/test/compile-fail/struct-fields-too-many.rs +++ b/src/test/compile-fail/struct-fields-too-many.rs @@ -15,6 +15,6 @@ struct BuildData { fn main() { let foo = BuildData { foo: 0, - bar: 0 //~ ERROR structure `BuildData` has no field named `bar` + bar: 0 //~ ERROR struct `BuildData` has no field named `bar` }; } diff --git a/src/test/compile-fail/suggest-private-fields.rs b/src/test/compile-fail/suggest-private-fields.rs index 9c61f618e69..41bd00a518c 100644 --- a/src/test/compile-fail/suggest-private-fields.rs +++ b/src/test/compile-fail/suggest-private-fields.rs @@ -22,16 +22,16 @@ struct A { fn main () { // external crate struct let k = B { - aa: 20, //~ ERROR structure `xc::B` has no field named `aa` + aa: 20, //~ ERROR struct `xc::B` has no field named `aa` //~^ HELP did you mean `a`? - bb: 20, //~ ERROR structure `xc::B` has no field named `bb` + bb: 20, //~ ERROR struct `xc::B` has no field named `bb` //~^ HELP did you mean `a`? }; // local crate struct let l = A { - aa: 20, //~ ERROR structure `A` has no field named `aa` + aa: 20, //~ ERROR struct `A` has no field named `aa` //~^ HELP did you mean `a`? - bb: 20, //~ ERROR structure `A` has no field named `bb` + bb: 20, //~ ERROR struct `A` has no field named `bb` //~^ HELP did you mean `b`? }; } diff --git a/src/test/compile-fail/union/union-const-eval.rs b/src/test/compile-fail/union/union-const-eval.rs new file mode 100644 index 00000000000..b2bf173c59c --- /dev/null +++ b/src/test/compile-fail/union/union-const-eval.rs @@ -0,0 +1,26 @@ +// 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. + +#![feature(untagged_unions)] + +union U { + a: usize, + b: usize, +} + +const C: U = U { a: 10 }; + +fn main() { + unsafe { + let a: [u8; C.a]; // OK + let b: [u8; C.b]; //~ ERROR constant evaluation error + //~^ NOTE nonexistent struct field + } +} diff --git a/src/test/compile-fail/union/union-const-pat.rs b/src/test/compile-fail/union/union-const-pat.rs new file mode 100644 index 00000000000..3d168980ed2 --- /dev/null +++ b/src/test/compile-fail/union/union-const-pat.rs @@ -0,0 +1,25 @@ +// 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. + +#![feature(untagged_unions)] + +union U { + a: usize, + b: usize, +} + +const C: U = U { a: 10 }; + +fn main() { + match C { + C => {} //~ ERROR cannot use unions in constant patterns + _ => {} + } +} diff --git a/src/test/compile-fail/union/union-copy.rs b/src/test/compile-fail/union/union-copy.rs new file mode 100644 index 00000000000..6e08ae0074d --- /dev/null +++ b/src/test/compile-fail/union/union-copy.rs @@ -0,0 +1,26 @@ +// 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. + +#![feature(untagged_unions)] + +union U { + a: u8 +} + +union W { + a: String +} + +impl Clone for U { fn clone(&self) { panic!(); } } +impl Clone for W { fn clone(&self) { panic!(); } } +impl Copy for U {} // OK +impl Copy for W {} //~ ERROR the trait `Copy` may not be implemented for this type + +fn main() {} diff --git a/src/test/compile-fail/union/union-derive.rs b/src/test/compile-fail/union/union-derive.rs new file mode 100644 index 00000000000..0f78e96f640 --- /dev/null +++ b/src/test/compile-fail/union/union-derive.rs @@ -0,0 +1,30 @@ +// 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. + +// Most traits cannot be derived for unions. + +#![feature(untagged_unions)] + +#[derive( + Clone, //~ ERROR this trait cannot be derived for unions + PartialEq, //~ ERROR this trait cannot be derived for unions + Eq, //~ ERROR this trait cannot be derived for unions + PartialOrd, //~ ERROR this trait cannot be derived for unions + Ord, //~ ERROR this trait cannot be derived for unions + Hash, //~ ERROR this trait cannot be derived for unions + Default, //~ ERROR this trait cannot be derived for unions + Debug, //~ ERROR this trait cannot be derived for unions +)] +union U { + a: u8, + b: u16, +} + +fn main() {} diff --git a/src/test/compile-fail/union/union-empty.rs b/src/test/compile-fail/union/union-empty.rs new file mode 100644 index 00000000000..ce5bbf60fee --- /dev/null +++ b/src/test/compile-fail/union/union-empty.rs @@ -0,0 +1,15 @@ +// 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. + +#![feature(untagged_unions)] + +union U {} //~ ERROR unions cannot have zero fields + +fn main() {} diff --git a/src/test/compile-fail/union/union-feature-gate.rs b/src/test/compile-fail/union/union-feature-gate.rs new file mode 100644 index 00000000000..abfc4d90921 --- /dev/null +++ b/src/test/compile-fail/union/union-feature-gate.rs @@ -0,0 +1,15 @@ +// 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. + +union U { //~ ERROR unions are unstable and possibly buggy + a: u8, +} + +fn main() {} diff --git a/src/test/compile-fail/union/union-fields.rs b/src/test/compile-fail/union/union-fields.rs new file mode 100644 index 00000000000..a1721dda7de --- /dev/null +++ b/src/test/compile-fail/union/union-fields.rs @@ -0,0 +1,35 @@ +// 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. + +#![feature(untagged_unions)] + +union U { + a: u8, + b: u16, +} + +fn main() { + let u = U {}; //~ ERROR union expressions should have exactly one field + let u = U { a: 0 }; // OK + let u = U { a: 0, b: 1 }; //~ ERROR union expressions should have exactly one field + let u = U { a: 0, b: 1, c: 2 }; //~ ERROR union expressions should have exactly one field + //~^ ERROR union `U` has no field named `c` + let u = U { ..u }; //~ ERROR union expressions should have exactly one field + //~^ ERROR functional record update syntax requires a struct + + let U {} = u; //~ ERROR union patterns should have exactly one field + let U { a } = u; // OK + let U { a, b } = u; //~ ERROR union patterns should have exactly one field + let U { a, b, c } = u; //~ ERROR union patterns should have exactly one field + //~^ ERROR union `U` does not have a field named `c` + let U { .. } = u; //~ ERROR union patterns should have exactly one field + //~^ ERROR `..` cannot be used in union patterns + let U { a, .. } = u; //~ ERROR `..` cannot be used in union patterns +} diff --git a/src/test/compile-fail/union/union-generic.rs b/src/test/compile-fail/union/union-generic.rs new file mode 100644 index 00000000000..e6586b0fb7f --- /dev/null +++ b/src/test/compile-fail/union/union-generic.rs @@ -0,0 +1,24 @@ +// 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. + +#![feature(untagged_unions)] + +use std::rc::Rc; + +union U<T: Copy> { + a: T +} + +fn main() { + let u = U { a: Rc::new(0u32) }; + //~^ ERROR the trait bound `std::rc::Rc<u32>: std::marker::Copy` is not satisfied + let u = U::<Rc<u32>> { a: Default::default() }; + //~^ ERROR the trait bound `std::rc::Rc<u32>: std::marker::Copy` is not satisfied +} diff --git a/src/test/compile-fail/union/union-nonrepresentable.rs b/src/test/compile-fail/union/union-nonrepresentable.rs new file mode 100644 index 00000000000..cb4683c2a0e --- /dev/null +++ b/src/test/compile-fail/union/union-nonrepresentable.rs @@ -0,0 +1,18 @@ +// 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. + +#![feature(untagged_unions)] + +union U { //~ ERROR recursive type `U` has infinite size + a: u8, + b: U, +} + +fn main() {} diff --git a/src/test/compile-fail/union/union-repr-c.rs b/src/test/compile-fail/union/union-repr-c.rs new file mode 100644 index 00000000000..d7dfb126c93 --- /dev/null +++ b/src/test/compile-fail/union/union-repr-c.rs @@ -0,0 +1,29 @@ +// 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. + +#![feature(untagged_unions)] +#![allow(unused)] +#![deny(improper_ctypes)] + +#[repr(C)] +union U { + a: u8, +} + +union W { + a: u8, +} + +extern "C" { + static FOREIGN1: U; // OK + static FOREIGN2: W; //~ ERROR found union without foreign-function-safe representation +} + +fn main() {} diff --git a/src/test/compile-fail/union/union-suggest-field.rs b/src/test/compile-fail/union/union-suggest-field.rs new file mode 100644 index 00000000000..b05e9b6e273 --- /dev/null +++ b/src/test/compile-fail/union/union-suggest-field.rs @@ -0,0 +1,29 @@ +// 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. + +#![feature(untagged_unions)] + +union U { + principal: u8, +} + +impl U { + fn calculate(&self) {} +} + +fn main() { + let u = U { principle: 0 }; //~ ERROR union `U` has no field named `principle` + //~^ HELP did you mean `principal`? + let w = u.principial; //~ ERROR attempted access of field `principial` on type `U` + //~^ HELP did you mean `principal`? + + let y = u.calculate; //~ ERROR attempted to take value of method `calculate` on type `U` + //~^ HELP maybe a `()` to call it is missing? +} diff --git a/src/test/compile-fail/union/union-unsafe.rs b/src/test/compile-fail/union/union-unsafe.rs new file mode 100644 index 00000000000..97e1ec2cba8 --- /dev/null +++ b/src/test/compile-fail/union/union-unsafe.rs @@ -0,0 +1,24 @@ +// 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. + +#![feature(untagged_unions)] + +union U { + a: u8 +} + +fn main() { + let mut u = U { a: 10 }; // OK + let a = u.a; //~ ERROR access to union field requires unsafe function or block + u.a = 11; //~ ERROR access to union field requires unsafe function or block + let U { a } = u; //~ ERROR matching on union field requires unsafe function or block + if let U { a: 12 } = u {} //~ ERROR matching on union field requires unsafe function or block + // let U { .. } = u; // OK +} diff --git a/src/test/compile-fail/union/union-unsized.rs b/src/test/compile-fail/union/union-unsized.rs new file mode 100644 index 00000000000..a238eaf0525 --- /dev/null +++ b/src/test/compile-fail/union/union-unsized.rs @@ -0,0 +1,23 @@ +// 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. + +#![feature(untagged_unions)] + +union U { + a: str, //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied + b: u8, +} + +union W { + a: u8, + b: str, //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied +} + +fn main() {} diff --git a/src/test/compile-fail/union/union-with-drop-fields-lint.rs b/src/test/compile-fail/union/union-with-drop-fields-lint.rs new file mode 100644 index 00000000000..87a72efbe08 --- /dev/null +++ b/src/test/compile-fail/union/union-with-drop-fields-lint.rs @@ -0,0 +1,40 @@ +// 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. + +#![feature(untagged_unions)] +#![allow(dead_code)] +#![deny(unions_with_drop_fields)] + +union U { + a: u8, // OK +} + +union W { + a: String, //~ ERROR union contains a field with possibly non-trivial drop code + b: String, // OK, only one field is reported +} + +struct S(String); + +// `S` doesn't implement `Drop` trait, but still has non-trivial destructor +union Y { + a: S, //~ ERROR union contains a field with possibly non-trivial drop code +} + +// We don't know if `T` is trivially-destructable or not until trans +union J<T> { + a: T, //~ ERROR union contains a field with possibly non-trivial drop code +} + +union H<T: Copy> { + a: T, // OK, `T` is `Copy`, no destructor +} + +fn main() {} |
