about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-10-21 22:00:45 +0200
committerGitHub <noreply@github.com>2019-10-21 22:00:45 +0200
commitaba84894d1879a7429d5bc20d0bfdca3471685de (patch)
tree5c11f19bd3b62b335a5a189f49b0ef2a6c3bc2f2 /src/libstd
parent10f12fe3e73f3b6f7e6d6f8bbd87b1a8b4e74a07 (diff)
parent875bdd5dbe663a6dafd785b86c8964a90653eeb7 (diff)
downloadrust-aba84894d1879a7429d5bc20d0bfdca3471685de.tar.gz
rust-aba84894d1879a7429d5bc20d0bfdca3471685de.zip
Rollup merge of #62330 - SimonSapin:no-drop-in-union-fields, r=RalfJung
Change untagged_unions to not allow union fields with drop

This is a rebase of #56440, massaged to solve merge conflicts and make the test suite pass.

Change untagged_unions to not allow union fields with drop

Union fields may now never have a type with attached destructor. This for example allows unions to use arbitrary field types only by wrapping them in `ManuallyDrop` (or similar).

The stable rule remains, that union fields must be `Copy`. We use the new rule for the `untagged_union` feature.

Tracking issue: https://github.com/rust-lang/rust/issues/55149
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/panicking.rs17
2 files changed, 9 insertions, 9 deletions
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 50a1226cc1d..93d3e4ea3df 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -275,6 +275,7 @@
 #![feature(link_args)]
 #![feature(linkage)]
 #![feature(log_syntax)]
+#![feature(manually_drop_take)]
 #![feature(maybe_uninit_ref)]
 #![feature(maybe_uninit_slice)]
 #![feature(needs_panic_runtime)]
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 638ce1679b8..2dde81bb0ec 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -12,8 +12,7 @@ use core::panic::{BoxMeUp, PanicInfo, Location};
 use crate::any::Any;
 use crate::fmt;
 use crate::intrinsics;
-use crate::mem;
-use crate::ptr;
+use crate::mem::{self, ManuallyDrop};
 use crate::raw;
 use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sys::stdio::panic_output;
@@ -227,10 +226,9 @@ pub use realstd::rt::update_panic_count;
 
 /// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
 pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
-    #[allow(unions_with_drop_fields)]
     union Data<F, R> {
-        f: F,
-        r: R,
+        f: ManuallyDrop<F>,
+        r: ManuallyDrop<R>,
     }
 
     // We do some sketchy operations with ownership here for the sake of
@@ -261,7 +259,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
     let mut any_data = 0;
     let mut any_vtable = 0;
     let mut data = Data {
-        f,
+        f: ManuallyDrop::new(f)
     };
 
     let r = __rust_maybe_catch_panic(do_call::<F, R>,
@@ -271,7 +269,7 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
 
     return if r == 0 {
         debug_assert!(update_panic_count(0) == 0);
-        Ok(data.r)
+        Ok(ManuallyDrop::into_inner(data.r))
     } else {
         update_panic_count(-1);
         debug_assert!(update_panic_count(0) == 0);
@@ -284,8 +282,9 @@ pub unsafe fn r#try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>>
     fn do_call<F: FnOnce() -> R, R>(data: *mut u8) {
         unsafe {
             let data = data as *mut Data<F, R>;
-            let f = ptr::read(&mut (*data).f);
-            ptr::write(&mut (*data).r, f());
+            let data = &mut (*data);
+            let f = ManuallyDrop::take(&mut data.f);
+            data.r = ManuallyDrop::new(f());
         }
     }
 }