Skip to content

Commit

Permalink
Rollup merge of rust-lang#75559 - RalfJung:union-test-move, r=joshtri…
Browse files Browse the repository at this point in the history
…plett

unions: test move behavior of non-Copy fields

This test ensures the behaviors suggested by @petrochenkov [here](rust-lang#32836 (comment)).
  • Loading branch information
RalfJung authored Sep 13, 2020
2 parents b6c8455 + 9c16cc2 commit 1500ced
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 1 deletion.
7 changes: 6 additions & 1 deletion src/test/ui/union/union-drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ fn main() {
{
let y = Y { a: S };
}
assert_eq!(CHECK, 2); // 2, dtor of Y is called
assert_eq!(CHECK, 2); // 2, Y has no dtor
{
let u2 = U { a: 1 };
std::mem::forget(u2);
}
assert_eq!(CHECK, 2); // 2, dtor of U *not* called for u2
}
}
53 changes: 53 additions & 0 deletions src/test/ui/union/union-move.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//! Test the behavior of moving out of non-`Copy` union fields.
//! Avoid types that `Drop`, we want to focus on moving.
#![feature(untagged_unions)]

use std::cell::RefCell;

fn move_out<T>(x: T) {}

union U1 {
f1_nocopy: RefCell<i32>,
f2_nocopy: RefCell<i32>,
f3_copy: i32,
}

union U2 {
f1_nocopy: RefCell<i32>,
}
impl Drop for U2 {
fn drop(&mut self) {}
}

fn test1(x: U1) {
// Moving out of a nocopy field prevents accessing other nocopy field.
unsafe {
move_out(x.f1_nocopy);
move_out(x.f2_nocopy); //~ ERROR use of moved value: `x`
}
}

fn test2(x: U1) {
// "Moving" out of copy field doesn't prevent later field accesses.
unsafe {
move_out(x.f3_copy);
move_out(x.f2_nocopy); // no error
}
}

fn test3(x: U1) {
// Moving out of a nocopy field prevents accessing other copy field.
unsafe {
move_out(x.f2_nocopy);
move_out(x.f3_copy); //~ ERROR use of moved value: `x`
}
}

fn test4(x: U2) {
// Cannot move out of union that implements `Drop`.
unsafe {
move_out(x.f1_nocopy); //~ ERROR cannot move out of type `U2`, which implements the `Drop`
}
}

fn main() {}
35 changes: 35 additions & 0 deletions src/test/ui/union/union-move.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
error[E0382]: use of moved value: `x`
--> $DIR/union-move.rs:26:18
|
LL | fn test1(x: U1) {
| - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
...
LL | move_out(x.f1_nocopy);
| ----------- value moved here
LL | move_out(x.f2_nocopy);
| ^^^^^^^^^^^ value used here after move

error[E0382]: use of moved value: `x`
--> $DIR/union-move.rs:42:18
|
LL | fn test3(x: U1) {
| - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
...
LL | move_out(x.f2_nocopy);
| ----------- value moved here
LL | move_out(x.f3_copy);
| ^^^^^^^^^ value used here after move

error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
--> $DIR/union-move.rs:49:18
|
LL | move_out(x.f1_nocopy);
| ^^^^^^^^^^^
| |
| cannot move out of here
| move occurs because `x.f1_nocopy` has type `std::cell::RefCell<i32>`, which does not implement the `Copy` trait

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0382, E0509.
For more information about an error, try `rustc --explain E0382`.

0 comments on commit 1500ced

Please sign in to comment.