From 9ee846bfd9acf998a6072df8fa4eb6798e32f035 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 21 Jul 2015 14:11:50 -0700 Subject: [PATCH 1/2] expose drop_in_place as ptr::drop_in_place --- src/liballoc/lib.rs | 2 ++ src/libcore/intrinsics.rs | 21 ++++++++++++++++++++- src/libcore/ptr.rs | 2 ++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 630993d829120..7af12915d4d21 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -96,6 +96,8 @@ #![feature(unsize)] #![feature(core_slice_ext)] #![feature(core_str_ext)] +#![feature(drop_in_place)] + #![cfg_attr(stage0, feature(alloc_system))] #![cfg_attr(not(stage0), feature(needs_allocator))] diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 5cbca1ba4c683..4bc4af045e0d7 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -195,7 +195,26 @@ extern "rust-intrinsic" { pub fn size_of_val(_: &T) -> usize; pub fn min_align_of_val(_: &T) -> usize; - pub fn drop_in_place(_: *mut T); + + /// Executes the destructor (if any) of the pointed-to value. + /// + /// This has two usecases: + /// + /// * It is *required* to use `drop_in_place` to drop unsized types like + /// trait objects, because they can't be read out onto the stack and + /// dropped normally. + /// + /// * It is friendlier to the optimizer to do this over `ptr::read` when + /// dropping manually allocated memory (e.g. when writing Box/Rc/Vec), + /// as the compiler doesn't need to prove that it's sound to elide the + /// copy. + /// + /// # Undefined Behaviour + /// + /// This has all the same safety problems as `ptr::read` with respect to + /// invalid pointers, types, and double drops. + #[unstable(feature = "drop_in_place", reason = "just exposed, needs FCP", issue = "27908")] + pub fn drop_in_place(to_drop: *mut T); /// Gets a static string slice containing the name of a type. pub fn type_name() -> &'static str; diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index b7479b0c604f3..5eb502acb33a8 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -39,6 +39,8 @@ pub use intrinsics::copy; #[stable(feature = "rust1", since = "1.0.0")] pub use intrinsics::write_bytes; +pub use intrinsics::drop_in_place; + /// Creates a null raw pointer. /// /// # Examples From 3547e8c4758f1d0406cb256064af4d54bf0cab68 Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Wed, 19 Aug 2015 15:55:36 -0700 Subject: [PATCH 2/2] don't use drop_in_place as an intrinsic --- src/doc/nomicon/destructors.md | 15 ++++++--------- src/liballoc/arc.rs | 4 ++-- src/liballoc/rc.rs | 4 ++-- src/libcollections/lib.rs | 2 ++ src/libcollections/vec.rs | 4 ++-- src/libstd/lib.rs | 2 ++ src/libstd/thread/local.rs | 2 +- src/test/run-pass/extern_fat_drop.rs | 2 +- 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/doc/nomicon/destructors.md b/src/doc/nomicon/destructors.md index 29a866063e996..e9acc9c45b1c1 100644 --- a/src/doc/nomicon/destructors.md +++ b/src/doc/nomicon/destructors.md @@ -26,11 +26,10 @@ this is totally fine. For instance, a custom implementation of `Box` might write `Drop` like this: ```rust -#![feature(heap_api, core_intrinsics, unique)] +#![feature(heap_api, drop_in_place, unique)] use std::rt::heap; -use std::ptr::Unique; -use std::intrinsics::drop_in_place; +use std::ptr::{drop_in_place, Unique}; use std::mem; struct Box{ ptr: Unique } @@ -54,11 +53,10 @@ use-after-free the `ptr` because when drop exits, it becomes inacessible. However this wouldn't work: ```rust -#![feature(heap_api, core_intrinsics, unique)] +#![feature(heap_api, drop_in_place, unique)] use std::rt::heap; -use std::ptr::Unique; -use std::intrinsics::drop_in_place; +use std::ptr::{drop_in_place, Unique}; use std::mem; struct Box{ ptr: Unique } @@ -129,11 +127,10 @@ The classic safe solution to overriding recursive drop and allowing moving out of Self during `drop` is to use an Option: ```rust -#![feature(heap_api, core_intrinsics, unique)] +#![feature(heap_api, drop_in_place, unique)] use std::rt::heap; -use std::ptr::Unique; -use std::intrinsics::drop_in_place; +use std::ptr::{drop_in_place, Unique}; use std::mem; struct Box{ ptr: Unique } diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 8af4cee909519..fc2f126e2aa19 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -76,7 +76,7 @@ use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst}; use core::fmt; use core::cmp::Ordering; use core::mem::{align_of_val, size_of_val}; -use core::intrinsics::{drop_in_place, abort}; +use core::intrinsics::abort; use core::mem; use core::nonzero::NonZero; use core::ops::{Deref, CoerceUnsized}; @@ -265,7 +265,7 @@ impl Arc { // Destroy the data at this time, even though we may not free the box // allocation itself (there may still be weak pointers lying around). - drop_in_place(&mut (*ptr).data); + ptr::drop_in_place(&mut (*ptr).data); if self.inner().weak.fetch_sub(1, Release) == 1 { atomic::fence(Acquire); diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index c2d7febf98e5e..59537ea608fb1 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -159,7 +159,7 @@ use core::cell::Cell; use core::cmp::Ordering; use core::fmt; use core::hash::{Hasher, Hash}; -use core::intrinsics::{assume, drop_in_place, abort}; +use core::intrinsics::{assume, abort}; use core::marker::{self, Unsize}; use core::mem::{self, align_of, size_of, align_of_val, size_of_val, forget}; use core::nonzero::NonZero; @@ -417,7 +417,7 @@ impl Drop for Rc { self.dec_strong(); if self.strong() == 0 { // destroy the contained object - drop_in_place(&mut (*ptr).value); + ptr::drop_in_place(&mut (*ptr).value); // remove the implicit "strong weak" pointer now that we've // destroyed the contents. diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 702b01f0e2eee..164fd59d3559e 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -56,6 +56,8 @@ #![feature(unique)] #![feature(unsafe_no_drop_flag, filling_drop)] #![feature(utf8_error)] +#![feature(drop_in_place)] + #![cfg_attr(test, feature(rand, test))] #![feature(no_std)] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index ec3c36d0c8137..dcfd151eec372 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -65,7 +65,7 @@ use alloc::heap::EMPTY; use core::cmp::Ordering; use core::fmt; use core::hash::{self, Hash}; -use core::intrinsics::{arith_offset, assume, drop_in_place}; +use core::intrinsics::{arith_offset, assume}; use core::iter::FromIterator; use core::mem; use core::ops::{Index, IndexMut, Deref}; @@ -1329,7 +1329,7 @@ impl Drop for Vec { // don't need unsafe_no_drop_flag shenanigans anymore. if self.buf.unsafe_no_drop_flag_needs_drop() { for x in self.iter_mut() { - unsafe { drop_in_place(x); } + unsafe { ptr::drop_in_place(x); } } } // RawVec handles deallocation diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index bc7252fa33a86..44b8f02423fc1 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -245,6 +245,8 @@ #![feature(vec_resize)] #![feature(wrapping)] #![feature(zero_one)] +#![feature(drop_in_place)] + #![cfg_attr(windows, feature(str_utf16))] #![cfg_attr(test, feature(float_from_str_radix, range_inclusive, float_extras, hash_default))] #![cfg_attr(test, feature(test, rustc_private, float_consts))] diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index c204f79614ad8..119429cc584f7 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -411,7 +411,7 @@ mod imp { if cfg!(target_os = "macos") { ptr::read((*ptr).inner.get()); } else { - intrinsics::drop_in_place((*ptr).inner.get()); + ptr::drop_in_place((*ptr).inner.get()); } } } diff --git a/src/test/run-pass/extern_fat_drop.rs b/src/test/run-pass/extern_fat_drop.rs index f587dc7821df0..7c627dc2937b2 100644 --- a/src/test/run-pass/extern_fat_drop.rs +++ b/src/test/run-pass/extern_fat_drop.rs @@ -10,7 +10,7 @@ // aux-build:fat_drop.rs -#![feature(core_intrinsics)] +#![feature(core_intrinsics, drop_in_place)] extern crate fat_drop;