Skip to content

Commit 409eb89

Browse files
Rollup merge of #75559 - RalfJung:union-test-move, r=joshtriplett
unions: test move behavior of non-Copy fields This test ensures the behaviors suggested by @petrochenkov [here](#32836 (comment)).
2 parents 7402a39 + 5dfe015 commit 409eb89

File tree

3 files changed

+94
-1
lines changed

3 files changed

+94
-1
lines changed

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ fn main() {
4848
{
4949
let y = Y { a: S };
5050
}
51-
assert_eq!(CHECK, 2); // 2, dtor of Y is called
51+
assert_eq!(CHECK, 2); // 2, Y has no dtor
52+
{
53+
let u2 = U { a: 1 };
54+
std::mem::forget(u2);
55+
}
56+
assert_eq!(CHECK, 2); // 2, dtor of U *not* called for u2
5257
}
5358
}

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

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//! Test the behavior of moving out of non-`Copy` union fields.
2+
//! Avoid types that `Drop`, we want to focus on moving.
3+
#![feature(untagged_unions)]
4+
5+
use std::cell::RefCell;
6+
7+
fn move_out<T>(x: T) {}
8+
9+
union U1 {
10+
f1_nocopy: RefCell<i32>,
11+
f2_nocopy: RefCell<i32>,
12+
f3_copy: i32,
13+
}
14+
15+
union U2 {
16+
f1_nocopy: RefCell<i32>,
17+
}
18+
impl Drop for U2 {
19+
fn drop(&mut self) {}
20+
}
21+
22+
fn test1(x: U1) {
23+
// Moving out of a nocopy field prevents accessing other nocopy field.
24+
unsafe {
25+
move_out(x.f1_nocopy);
26+
move_out(x.f2_nocopy); //~ ERROR use of moved value: `x`
27+
}
28+
}
29+
30+
fn test2(x: U1) {
31+
// "Moving" out of copy field doesn't prevent later field accesses.
32+
unsafe {
33+
move_out(x.f3_copy);
34+
move_out(x.f2_nocopy); // no error
35+
}
36+
}
37+
38+
fn test3(x: U1) {
39+
// Moving out of a nocopy field prevents accessing other copy field.
40+
unsafe {
41+
move_out(x.f2_nocopy);
42+
move_out(x.f3_copy); //~ ERROR use of moved value: `x`
43+
}
44+
}
45+
46+
fn test4(x: U2) {
47+
// Cannot move out of union that implements `Drop`.
48+
unsafe {
49+
move_out(x.f1_nocopy); //~ ERROR cannot move out of type `U2`, which implements the `Drop`
50+
}
51+
}
52+
53+
fn main() {}

src/test/ui/union/union-move.stderr

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error[E0382]: use of moved value: `x`
2+
--> $DIR/union-move.rs:26:18
3+
|
4+
LL | fn test1(x: U1) {
5+
| - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
6+
...
7+
LL | move_out(x.f1_nocopy);
8+
| ----------- value moved here
9+
LL | move_out(x.f2_nocopy);
10+
| ^^^^^^^^^^^ value used here after move
11+
12+
error[E0382]: use of moved value: `x`
13+
--> $DIR/union-move.rs:42:18
14+
|
15+
LL | fn test3(x: U1) {
16+
| - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
17+
...
18+
LL | move_out(x.f2_nocopy);
19+
| ----------- value moved here
20+
LL | move_out(x.f3_copy);
21+
| ^^^^^^^^^ value used here after move
22+
23+
error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
24+
--> $DIR/union-move.rs:49:18
25+
|
26+
LL | move_out(x.f1_nocopy);
27+
| ^^^^^^^^^^^
28+
| |
29+
| cannot move out of here
30+
| move occurs because `x.f1_nocopy` has type `RefCell<i32>`, which does not implement the `Copy` trait
31+
32+
error: aborting due to 3 previous errors
33+
34+
Some errors have detailed explanations: E0382, E0509.
35+
For more information about an error, try `rustc --explain E0382`.

0 commit comments

Comments
 (0)