From 2375dc0305a39ad4df742dc58a5b9588aeac7934 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Aug 2020 13:04:32 +0200 Subject: [PATCH 1/3] unions: test move behavior of non-Copy fields --- src/test/ui/union/union-drop.rs | 5 +++ src/test/ui/union/union-move.rs | 53 +++++++++++++++++++++++++++++ src/test/ui/union/union-move.stderr | 35 +++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 src/test/ui/union/union-move.rs create mode 100644 src/test/ui/union/union-move.stderr diff --git a/src/test/ui/union/union-drop.rs b/src/test/ui/union/union-drop.rs index daa03ce6b6fd8..d7d5610cd6a6f 100644 --- a/src/test/ui/union/union-drop.rs +++ b/src/test/ui/union/union-drop.rs @@ -49,5 +49,10 @@ fn main() { let y = Y { a: S }; } assert_eq!(CHECK, 2); // 2, dtor of Y is called + { + let y2 = Y { a: S }; + std::mem::forget(y2); + } + assert_eq!(CHECK, 2); // 2, dtor of Y *not* called for y2 } } diff --git a/src/test/ui/union/union-move.rs b/src/test/ui/union/union-move.rs new file mode 100644 index 0000000000000..b19b61282f06a --- /dev/null +++ b/src/test/ui/union/union-move.rs @@ -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(x: T) {} + +union U1 { + f1_nocopy: RefCell, + f2_nocopy: RefCell, + f3_copy: i32, +} + +union U2 { + f1_nocopy: RefCell, +} +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` trait + } +} + +fn main() {} diff --git a/src/test/ui/union/union-move.stderr b/src/test/ui/union/union-move.stderr new file mode 100644 index 0000000000000..4a29f3a77f3c9 --- /dev/null +++ b/src/test/ui/union/union-move.stderr @@ -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`, 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`. From fe21e4c2f56855b3fc80351d23272dbf72820eca Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Aug 2020 19:38:01 +0200 Subject: [PATCH 2/3] please tidy --- src/test/ui/union/union-move.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/union/union-move.rs b/src/test/ui/union/union-move.rs index b19b61282f06a..a0a2d0d659837 100644 --- a/src/test/ui/union/union-move.rs +++ b/src/test/ui/union/union-move.rs @@ -46,7 +46,7 @@ fn test3(x: U1) { 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` trait + move_out(x.f1_nocopy); //~ ERROR cannot move out of type `U2`, which implements the `Drop` } } From 9c16cc276371e66a91731e150d21647b7975a5ef Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 30 Aug 2020 18:59:57 +0200 Subject: [PATCH 3/3] make union-drop mem::forget test meaningful --- src/test/ui/union/union-drop.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/ui/union/union-drop.rs b/src/test/ui/union/union-drop.rs index d7d5610cd6a6f..4df3ed502827e 100644 --- a/src/test/ui/union/union-drop.rs +++ b/src/test/ui/union/union-drop.rs @@ -48,11 +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 y2 = Y { a: S }; - std::mem::forget(y2); + let u2 = U { a: 1 }; + std::mem::forget(u2); } - assert_eq!(CHECK, 2); // 2, dtor of Y *not* called for y2 + assert_eq!(CHECK, 2); // 2, dtor of U *not* called for u2 } }