about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2020-08-15 13:04:32 +0200
committerRalf Jung <post@ralfj.de>2020-09-13 16:13:20 +0200
commitc95fa0ac76c3cbe930e021d02750aa28b169a949 (patch)
tree6fd8756dbd60252575427fe8ca4aa00166a29515
parentb6c84553c4fa47174d2510541a90243000fb44d8 (diff)
downloadrust-c95fa0ac76c3cbe930e021d02750aa28b169a949.tar.gz
rust-c95fa0ac76c3cbe930e021d02750aa28b169a949.zip
unions: test move behavior of non-Copy fields
-rw-r--r--src/test/ui/union/union-drop.rs5
-rw-r--r--src/test/ui/union/union-move.rs53
-rw-r--r--src/test/ui/union/union-move.stderr35
3 files changed, 93 insertions, 0 deletions
diff --git a/src/test/ui/union/union-drop.rs b/src/test/ui/union/union-drop.rs
index daa03ce6b6f..d7d5610cd6a 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 00000000000..b19b61282f0
--- /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<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` 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 00000000000..4a29f3a77f3
--- /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<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`.