Skip to content

Commit 0950bdf

Browse files
committed
Update ui tests for union fields with drop rule change
Note: We can't test move out through Box's deref-move since we can't have a Box in a union anymore.
1 parent 776d5d4 commit 0950bdf

9 files changed

+191
-92
lines changed

src/test/ui/union/union-borrow-move-parent-sibling.rs

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,91 @@
11
#![feature(untagged_unions)]
22
#![allow(unused)]
33

4+
use std::ops::{Deref, DerefMut};
5+
6+
#[derive(Default)]
7+
struct MockBox<T> {
8+
value: [T; 1],
9+
}
10+
11+
impl<T> MockBox<T> {
12+
fn new(value: T) -> Self { MockBox { value: [value] } }
13+
}
14+
15+
impl<T> Deref for MockBox<T> {
16+
type Target = T;
17+
fn deref(&self) -> &T { &self.value[0] }
18+
}
19+
20+
impl<T> DerefMut for MockBox<T> {
21+
fn deref_mut(&mut self) -> &mut T { &mut self.value[0] }
22+
}
23+
24+
#[derive(Default)]
25+
struct MockVec<T> {
26+
value: [T; 0],
27+
}
28+
29+
impl<T> MockVec<T> {
30+
fn new() -> Self { MockVec { value: [] } }
31+
}
32+
33+
impl<T> Deref for MockVec<T> {
34+
type Target = [T];
35+
fn deref(&self) -> &[T] { &self.value }
36+
}
37+
38+
impl<T> DerefMut for MockVec<T> {
39+
fn deref_mut(&mut self) -> &mut [T] { &mut self.value }
40+
}
41+
42+
443
#[allow(unions_with_drop_fields)]
544
union U {
6-
x: ((Vec<u8>, Vec<u8>), Vec<u8>),
7-
y: Box<Vec<u8>>,
45+
x: ((MockVec<u8>, MockVec<u8>), MockVec<u8>),
46+
y: MockBox<MockVec<u8>>,
847
}
948

1049
fn use_borrow<T>(_: &T) {}
1150

1251
unsafe fn parent_sibling_borrow() {
13-
let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
52+
let mut u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
1453
let a = &mut u.x.0;
1554
let b = &u.y; //~ ERROR cannot borrow `u.y`
1655
use_borrow(a);
1756
}
1857

1958
unsafe fn parent_sibling_move() {
20-
let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
59+
let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
2160
let a = u.x.0;
2261
let b = u.y; //~ ERROR use of moved value: `u.y`
2362
}
2463

2564
unsafe fn grandparent_sibling_borrow() {
26-
let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
65+
let mut u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
2766
let a = &mut (u.x.0).0;
2867
let b = &u.y; //~ ERROR cannot borrow `u.y`
2968
use_borrow(a);
3069
}
3170

3271
unsafe fn grandparent_sibling_move() {
33-
let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
72+
let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
3473
let a = (u.x.0).0;
3574
let b = u.y; //~ ERROR use of moved value: `u.y`
3675
}
3776

3877
unsafe fn deref_sibling_borrow() {
39-
let mut u = U { y: Box::default() };
78+
let mut u = U { y: MockBox::default() };
4079
let a = &mut *u.y;
4180
let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
4281
use_borrow(a);
4382
}
4483

4584
unsafe fn deref_sibling_move() {
46-
let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
47-
let a = *u.y;
48-
let b = u.x; //~ ERROR use of moved value: `u.x`
85+
let u = U { x: ((MockVec::new(), MockVec::new()), MockVec::new()) };
86+
// No way to test deref-move without Box in union
87+
// let a = *u.y;
88+
// let b = u.x; ERROR use of moved value: `u.x`
4989
}
5090

5191

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0502]: cannot borrow `u.y` as immutable because `u.x.0` is also borrowed as mutable
2-
--> $DIR/union-borrow-move-parent-sibling.rs:15:14
2+
--> $DIR/union-borrow-move-parent-sibling.rs:54:14
33
|
44
LL | let a = &mut u.x.0;
55
| ----- mutable borrow occurs here
@@ -10,7 +10,7 @@ LL | }
1010
| - mutable borrow ends here
1111

1212
error[E0382]: use of moved value: `u.y`
13-
--> $DIR/union-borrow-move-parent-sibling.rs:22:9
13+
--> $DIR/union-borrow-move-parent-sibling.rs:61:9
1414
|
1515
LL | let a = u.x.0;
1616
| - value moved here
@@ -20,7 +20,7 @@ LL | let b = u.y; //~ ERROR use of moved value: `u.y`
2020
= note: move occurs because `u.y` has type `[type error]`, which does not implement the `Copy` trait
2121

2222
error[E0502]: cannot borrow `u.y` as immutable because `u.x.0.0` is also borrowed as mutable
23-
--> $DIR/union-borrow-move-parent-sibling.rs:28:14
23+
--> $DIR/union-borrow-move-parent-sibling.rs:67:14
2424
|
2525
LL | let a = &mut (u.x.0).0;
2626
| --------- mutable borrow occurs here
@@ -31,7 +31,7 @@ LL | }
3131
| - mutable borrow ends here
3232

3333
error[E0382]: use of moved value: `u.y`
34-
--> $DIR/union-borrow-move-parent-sibling.rs:35:9
34+
--> $DIR/union-borrow-move-parent-sibling.rs:74:9
3535
|
3636
LL | let a = (u.x.0).0;
3737
| - value moved here
@@ -40,28 +40,18 @@ LL | let b = u.y; //~ ERROR use of moved value: `u.y`
4040
|
4141
= note: move occurs because `u.y` has type `[type error]`, which does not implement the `Copy` trait
4242

43-
error[E0502]: cannot borrow `u` (via `u.x`) as immutable because `u` is also borrowed as mutable (via `*u.y`)
44-
--> $DIR/union-borrow-move-parent-sibling.rs:41:14
43+
error[E0502]: cannot borrow `u` (via `u.x`) as immutable because `u` is also borrowed as mutable (via `u.y`)
44+
--> $DIR/union-borrow-move-parent-sibling.rs:80:14
4545
|
4646
LL | let a = &mut *u.y;
47-
| ---- mutable borrow occurs here (via `*u.y`)
47+
| --- mutable borrow occurs here (via `u.y`)
4848
LL | let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
4949
| ^^^ immutable borrow occurs here (via `u.x`)
5050
LL | use_borrow(a);
5151
LL | }
5252
| - mutable borrow ends here
5353

54-
error[E0382]: use of moved value: `u.x`
55-
--> $DIR/union-borrow-move-parent-sibling.rs:48:9
56-
|
57-
LL | let a = *u.y;
58-
| - value moved here
59-
LL | let b = u.x; //~ ERROR use of moved value: `u.x`
60-
| ^ value used here after move
61-
|
62-
= note: move occurs because `u.x` has type `[type error]`, which does not implement the `Copy` trait
63-
64-
error: aborting due to 6 previous errors
54+
error: aborting due to 5 previous errors
6555

6656
Some errors occurred: E0382, E0502.
6757
For more information about an error, try `rustc --explain E0382`.

src/test/ui/union/union-derive-clone.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#![feature(untagged_unions)]
22

3+
use std::mem::ManuallyDrop;
4+
35
#[derive(Clone)] //~ ERROR the trait bound `U1: std::marker::Copy` is not satisfied
46
union U1 {
57
a: u8,
@@ -18,14 +20,19 @@ union U3 {
1820
}
1921

2022
#[derive(Clone, Copy)]
21-
union U4<T> {
23+
union U4<T: Copy> {
2224
a: T, // OK
2325
}
2426

27+
#[derive(Clone, Copy)]
28+
union U5<T> {
29+
a: ManuallyDrop<T>, // OK
30+
}
31+
2532
#[derive(Clone)]
2633
struct CloneNoCopy;
2734

2835
fn main() {
29-
let u = U4 { a: CloneNoCopy };
30-
let w = u.clone(); //~ ERROR no method named `clone` found for type `U4<CloneNoCopy>`
36+
let u = U5 { a: ManuallyDrop::new(CloneNoCopy) };
37+
let w = u.clone(); //~ ERROR no method named `clone` found for type `U5<CloneNoCopy>`
3138
}

src/test/ui/union/union-derive-clone.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
error[E0277]: the trait bound `U1: std::marker::Copy` is not satisfied
2-
--> $DIR/union-derive-clone.rs:3:10
2+
--> $DIR/union-derive-clone.rs:5:10
33
|
44
LL | #[derive(Clone)] //~ ERROR the trait bound `U1: std::marker::Copy` is not satisfied
55
| ^^^^^ the trait `std::marker::Copy` is not implemented for `U1`
66
|
77
= note: required by `std::clone::AssertParamIsCopy`
88

9-
error[E0599]: no method named `clone` found for type `U4<CloneNoCopy>` in the current scope
10-
--> $DIR/union-derive-clone.rs:30:15
9+
error[E0599]: no method named `clone` found for type `U5<CloneNoCopy>` in the current scope
10+
--> $DIR/union-derive-clone.rs:37:15
1111
|
12-
LL | union U4<T> {
12+
LL | union U5<T> {
1313
| ----------- method `clone` not found for this
1414
...
15-
LL | let w = u.clone(); //~ ERROR no method named `clone` found for type `U4<CloneNoCopy>`
15+
LL | let w = u.clone(); //~ ERROR no method named `clone` found for type `U5<CloneNoCopy>`
1616
| ^^^^^
1717
|
1818
= note: the method `clone` exists but the following trait bounds were not satisfied:
19-
`U4<CloneNoCopy> : std::clone::Clone`
19+
`U5<CloneNoCopy> : std::clone::Clone`
2020
= help: items from traits can only be used if the trait is implemented and in scope
2121
= note: the following trait defines an item `clone`, perhaps you need to implement it:
2222
candidate #1: `std::clone::Clone`

src/test/ui/union/union-unsafe.rs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,33 @@
11
#![feature(untagged_unions)]
2+
use std::mem::ManuallyDrop;
23

34
union U1 {
45
a: u8
56
}
67

78
union U2 {
8-
a: String
9+
a: ManuallyDrop<String>
910
}
1011

1112
union U3<T> {
12-
a: T
13+
a: ManuallyDrop<T>
1314
}
1415

1516
union U4<T: Copy> {
1617
a: T
1718
}
1819

1920
fn generic_noncopy<T: Default>() {
20-
let mut u3 = U3 { a: T::default() };
21-
u3.a = T::default(); //~ ERROR assignment to non-`Copy` union field is unsafe
21+
let mut u3 = U3 { a: ManuallyDrop::new(T::default()) };
22+
u3.a = ManuallyDrop::new(T::default()); //~ ERROR assignment to non-`Copy` union field is unsafe
23+
*u3.a = T::default(); //~ ERROR access to union field is unsafe
2224
}
2325

2426
fn generic_copy<T: Copy + Default>() {
25-
let mut u3 = U3 { a: T::default() };
26-
u3.a = T::default(); // OK
27+
let mut u3 = U3 { a: ManuallyDrop::new(T::default()) };
28+
u3.a = ManuallyDrop::new(T::default()); // OK
29+
*u3.a = T::default(); //~ ERROR access to union field is unsafe
30+
2731
let mut u4 = U4 { a: T::default() };
2832
u4.a = T::default(); // OK
2933
}
@@ -32,14 +36,20 @@ fn main() {
3236
let mut u1 = U1 { a: 10 }; // OK
3337
let a = u1.a; //~ ERROR access to union field is unsafe
3438
u1.a = 11; // OK
39+
3540
let U1 { a } = u1; //~ ERROR access to union field is unsafe
3641
if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe
3742
// let U1 { .. } = u1; // OK
3843

39-
let mut u2 = U2 { a: String::from("old") }; // OK
40-
u2.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field is unsafe
41-
let mut u3 = U3 { a: 0 }; // OK
42-
u3.a = 1; // OK
43-
let mut u3 = U3 { a: String::from("old") }; // OK
44-
u3.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field is unsafe
44+
let mut u2 = U2 { a: ManuallyDrop::new(String::from("old")) }; // OK
45+
u2.a = ManuallyDrop::new(String::from("new")); //~ ERROR assignment to non-`Copy` union
46+
*u2.a = String::from("new"); //~ ERROR access to union field is unsafe
47+
48+
let mut u3 = U3 { a: ManuallyDrop::new(0) }; // OK
49+
u3.a = ManuallyDrop::new(1); // OK
50+
*u3.a = 1; //~ ERROR access to union field is unsafe
51+
52+
let mut u3 = U3 { a: ManuallyDrop::new(String::from("old")) }; // OK
53+
u3.a = ManuallyDrop::new(String::from("new")); //~ ERROR assignment to non-`Copy` union
54+
*u3.a = String::from("new"); //~ ERROR access to union field is unsafe
4555
}

0 commit comments

Comments
 (0)