Skip to content

Commit c37d66a

Browse files
Rollup merge of rust-lang#41892 - Gankro:needs_drop, r=alexcrichton
expose needs_drop under mem Note that I purposefully didn't update the intrinsic's documentation, because I think it makes sense for it be more... "honest" about its semantics.
2 parents 01951a6 + 1f01b09 commit c37d66a

File tree

7 files changed

+72
-13
lines changed

7 files changed

+72
-13
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# `needs_drop`
2+
3+
The tracking issue for this feature is: [#41890]
4+
5+
[#41890]: https://github.com/rust-lang/rust/issues/41890
6+
7+
------------------------

src/libarena/lib.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#![feature(core_intrinsics)]
3333
#![feature(dropck_eyepatch)]
3434
#![feature(generic_param_attrs)]
35+
#![feature(needs_drop)]
3536
#![cfg_attr(stage0, feature(staged_api))]
3637
#![cfg_attr(test, feature(test))]
3738

@@ -82,7 +83,7 @@ impl<T> TypedArenaChunk<T> {
8283
unsafe fn destroy(&mut self, len: usize) {
8384
// The branch on needs_drop() is an -O1 performance optimization.
8485
// Without the branch, dropping TypedArena<u8> takes linear time.
85-
if intrinsics::needs_drop::<T>() {
86+
if mem::needs_drop::<T>() {
8687
let mut start = self.start();
8788
// Destroy all allocated objects.
8889
for _ in 0..len {
@@ -350,7 +351,7 @@ impl DroplessArena {
350351
#[inline]
351352
pub fn alloc<T>(&self, object: T) -> &mut T {
352353
unsafe {
353-
assert!(!intrinsics::needs_drop::<T>());
354+
assert!(!mem::needs_drop::<T>());
354355
assert!(mem::size_of::<T>() != 0);
355356

356357
self.align_for::<T>();
@@ -379,9 +380,7 @@ impl DroplessArena {
379380
#[inline]
380381
pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
381382
where T: Copy {
382-
unsafe {
383-
assert!(!intrinsics::needs_drop::<T>());
384-
}
383+
assert!(!mem::needs_drop::<T>());
385384
assert!(mem::size_of::<T>() != 0);
386385
assert!(slice.len() != 0);
387386
self.align_for::<T>();

src/libcore/mem.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,58 @@ pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
302302
unsafe { intrinsics::min_align_of_val(val) }
303303
}
304304

305+
/// Returns whether dropping values of type `T` matters.
306+
///
307+
/// This is purely an optimization hint, and may be implemented conservatively.
308+
/// For instance, always returning `true` would be a valid implementation of
309+
/// this function.
310+
///
311+
/// Low level implementations of things like collections, which need to manually
312+
/// drop their data, should use this function to avoid unnecessarily
313+
/// trying to drop all their contents when they are destroyed. This might not
314+
/// make a difference in release builds (where a loop that has no side-effects
315+
/// is easily detected and eliminated), but is often a big win for debug builds.
316+
///
317+
/// Note that `ptr::drop_in_place` already performs this check, so if your workload
318+
/// can be reduced to some small number of drop_in_place calls, using this is
319+
/// unnecessary. In particular note that you can drop_in_place a slice, and that
320+
/// will do a single needs_drop check for all the values.
321+
///
322+
/// Types like Vec therefore just `drop_in_place(&mut self[..])` without using
323+
/// needs_drop explicitly. Types like HashMap, on the other hand, have to drop
324+
/// values one at a time and should use this API.
325+
///
326+
///
327+
/// # Examples
328+
///
329+
/// Here's an example of how a collection might make use of needs_drop:
330+
///
331+
/// ```ignore
332+
/// #![feature(needs_drop)]
333+
/// use std::{mem, ptr};
334+
///
335+
/// pub struct MyCollection<T> { /* ... */ }
336+
///
337+
/// impl<T> Drop for MyCollection<T> {
338+
/// fn drop(&mut self) {
339+
/// unsafe {
340+
/// // drop the data
341+
/// if mem::needs_drop::<T>() {
342+
/// for x in self.iter_mut() {
343+
/// ptr::drop_in_place(x);
344+
/// }
345+
/// }
346+
/// self.free_buffer();
347+
/// }
348+
/// }
349+
/// }
350+
/// ```
351+
#[inline]
352+
#[unstable(feature = "needs_drop", issue = "41890")]
353+
pub fn needs_drop<T>() -> bool {
354+
unsafe { intrinsics::needs_drop::<T>() }
355+
}
356+
305357
/// Creates a value whose bytes are all zero.
306358
///
307359
/// This has the same effect as allocating space with

src/libstd/collections/hash/table.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ use alloc::heap::{allocate, deallocate};
1212

1313
use cmp;
1414
use hash::{BuildHasher, Hash, Hasher};
15-
use intrinsics::needs_drop;
1615
use marker;
17-
use mem::{align_of, size_of};
16+
use mem::{align_of, size_of, needs_drop};
1817
use mem;
1918
use ops::{Deref, DerefMut};
2019
use ptr::{self, Unique, Shared};

src/libstd/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@
281281
#![feature(linkage)]
282282
#![feature(macro_reexport)]
283283
#![feature(needs_panic_runtime)]
284+
#![feature(needs_drop)]
284285
#![feature(never_type)]
285286
#![feature(num_bits_bytes)]
286287
#![feature(old_wrapping)]

src/libstd/sys/redox/fast_thread_local.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
#![unstable(feature = "thread_local_internals", issue = "0")]
1313

1414
use cell::{Cell, UnsafeCell};
15-
use intrinsics;
15+
use mem;
1616
use ptr;
1717

18+
1819
pub struct Key<T> {
1920
inner: UnsafeCell<Option<T>>,
2021

@@ -37,7 +38,7 @@ impl<T> Key<T> {
3738

3839
pub fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
3940
unsafe {
40-
if intrinsics::needs_drop::<T>() && self.dtor_running.get() {
41+
if mem::needs_drop::<T>() && self.dtor_running.get() {
4142
return None
4243
}
4344
self.register_dtor();
@@ -46,7 +47,7 @@ impl<T> Key<T> {
4647
}
4748

4849
unsafe fn register_dtor(&self) {
49-
if !intrinsics::needs_drop::<T>() || self.dtor_registered.get() {
50+
if !mem::needs_drop::<T>() || self.dtor_registered.get() {
5051
return
5152
}
5253

src/libstd/sys/unix/fast_thread_local.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
use cell::{Cell, UnsafeCell};
1515
use fmt;
16-
use intrinsics;
16+
use mem;
1717
use ptr;
1818

1919
pub struct Key<T> {
@@ -44,7 +44,7 @@ impl<T> Key<T> {
4444

4545
pub fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
4646
unsafe {
47-
if intrinsics::needs_drop::<T>() && self.dtor_running.get() {
47+
if mem::needs_drop::<T>() && self.dtor_running.get() {
4848
return None
4949
}
5050
self.register_dtor();
@@ -53,7 +53,7 @@ impl<T> Key<T> {
5353
}
5454

5555
unsafe fn register_dtor(&self) {
56-
if !intrinsics::needs_drop::<T>() || self.dtor_registered.get() {
56+
if !mem::needs_drop::<T>() || self.dtor_registered.get() {
5757
return
5858
}
5959

0 commit comments

Comments
 (0)