diff options
| author | bors <bors@rust-lang.org> | 2017-04-12 00:45:49 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-04-12 00:45:49 +0000 |
| commit | da32752d92589e99feab80921b9eecb6090cf310 (patch) | |
| tree | 9832f02c18cd5bb0ad0b33607ea46912e4974b50 /src/libcore | |
| parent | f8107c0d7ce4f39364fc96d0eeb6a23673491f81 (diff) | |
| parent | 72538dee4dbfe28882ae5ff37d4ae0cdafe758d5 (diff) | |
| download | rust-da32752d92589e99feab80921b9eecb6090cf310.tar.gz rust-da32752d92589e99feab80921b9eecb6090cf310.zip | |
Auto merge of #41237 - frewsxcv:rollup, r=frewsxcv
Rollup of 8 pull requests - Successful merges: #40377, #40559, #41173, #41202, #41204, #41209, #41216, #41231 - Failed merges:
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/intrinsics.rs | 3 | ||||
| -rw-r--r-- | src/libcore/iter/iterator.rs | 8 | ||||
| -rw-r--r-- | src/libcore/mem.rs | 120 | ||||
| -rw-r--r-- | src/libcore/slice/sort.rs | 30 |
4 files changed, 137 insertions, 24 deletions
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index e0a4707ff66..b0287631585 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -691,9 +691,6 @@ extern "rust-intrinsic" { /// initialize memory previous set to the result of `uninit`. pub fn uninit<T>() -> T; - /// Moves a value out of scope without running drop glue. - pub fn forget<T>(_: T) -> (); - /// Reinterprets the bits of a value of one type as another type. /// /// Both types must have the same size. Neither the original, nor the result, diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 618edf48abd..8bf641e37fe 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1532,14 +1532,18 @@ pub trait Iterator { /// Stopping at the first `true`: /// /// ``` - /// let a = [1, 2, 3]; + /// let a = [1, 2, 3, 4]; /// /// let mut iter = a.iter(); /// - /// assert_eq!(iter.position(|&x| x == 2), Some(1)); + /// assert_eq!(iter.position(|&x| x >= 2), Some(1)); /// /// // we can still use `iter`, as there are more elements. /// assert_eq!(iter.next(), Some(&3)); + /// + /// // The returned index depends on iterator state + /// assert_eq!(iter.position(|&x| x == 4), Some(0)); + /// /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index f5cf3724d07..7be927b28ed 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -171,7 +171,7 @@ pub use intrinsics::transmute; #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn forget<T>(t: T) { - unsafe { intrinsics::forget(t) } + ManuallyDrop::new(t); } /// Returns the size of a type in bytes. @@ -736,3 +736,121 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> { } } + +/// A wrapper to inhibit compiler from automatically calling `T`’s destructor. +/// +/// This wrapper is 0-cost. +/// +/// # Examples +/// +/// This wrapper helps with explicitly documenting the drop order dependencies between fields of +/// the type: +/// +/// ```rust +/// # #![feature(manually_drop)] +/// use std::mem::ManuallyDrop; +/// struct Peach; +/// struct Banana; +/// struct Melon; +/// struct FruitBox { +/// // Immediately clear there’s something non-trivial going on with these fields. +/// peach: ManuallyDrop<Peach>, +/// melon: Melon, // Field that’s independent of the other two. +/// banana: ManuallyDrop<Banana>, +/// } +/// +/// impl Drop for FruitBox { +/// fn drop(&mut self) { +/// unsafe { +/// // Explicit ordering in which field destructors are run specified in the intuitive +/// // location – the destructor of the structure containing the fields. +/// // Moreover, one can now reorder fields within the struct however much they want. +/// ManuallyDrop::drop(&mut self.peach); +/// ManuallyDrop::drop(&mut self.banana); +/// } +/// // After destructor for `FruitBox` runs (this function), the destructor for Melon gets +/// // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`. +/// } +/// } +/// ``` +#[unstable(feature = "manually_drop", issue = "40673")] +#[allow(unions_with_drop_fields)] +pub union ManuallyDrop<T>{ value: T } + +impl<T> ManuallyDrop<T> { + /// Wrap a value to be manually dropped. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(manually_drop)] + /// use std::mem::ManuallyDrop; + /// ManuallyDrop::new(Box::new(())); + /// ``` + #[unstable(feature = "manually_drop", issue = "40673")] + #[inline] + pub fn new(value: T) -> ManuallyDrop<T> { + ManuallyDrop { value: value } + } + + /// Extract the value from the ManuallyDrop container. + /// + /// # Examples + /// + /// ```rust + /// # #![feature(manually_drop)] + /// use std::mem::ManuallyDrop; + /// let x = ManuallyDrop::new(Box::new(())); + /// let _: Box<()> = ManuallyDrop::into_inner(x); + /// ``` + #[unstable(feature = "manually_drop", issue = "40673")] + #[inline] + pub fn into_inner(slot: ManuallyDrop<T>) -> T { + unsafe { + slot.value + } + } + + /// Manually drops the contained value. + /// + /// # Unsafety + /// + /// This function runs the destructor of the contained value and thus the wrapped value + /// now represents uninitialized data. It is up to the user of this method to ensure the + /// uninitialized data is not actually used. + #[unstable(feature = "manually_drop", issue = "40673")] + #[inline] + pub unsafe fn drop(slot: &mut ManuallyDrop<T>) { + ptr::drop_in_place(&mut slot.value) + } +} + +#[unstable(feature = "manually_drop", issue = "40673")] +impl<T> ::ops::Deref for ManuallyDrop<T> { + type Target = T; + #[inline] + fn deref(&self) -> &Self::Target { + unsafe { + &self.value + } + } +} + +#[unstable(feature = "manually_drop", issue = "40673")] +impl<T> ::ops::DerefMut for ManuallyDrop<T> { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { + &mut self.value + } + } +} + +#[unstable(feature = "manually_drop", issue = "40673")] +impl<T: ::fmt::Debug> ::fmt::Debug for ManuallyDrop<T> { + fn fmt(&self, fmt: &mut ::fmt::Formatter) -> ::fmt::Result { + unsafe { + fmt.debug_tuple("ManuallyDrop").field(&self.value).finish() + } + } +} diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs index 7065fdb79fc..6f9f2915dfe 100644 --- a/src/libcore/slice/sort.rs +++ b/src/libcore/slice/sort.rs @@ -20,12 +20,6 @@ use cmp; use mem; use ptr; -/// Holds a value, but never drops it. -#[allow(unions_with_drop_fields)] -union NoDrop<T> { - value: T -} - /// When dropped, copies from `src` into `dest`. struct CopyOnDrop<T> { src: *mut T, @@ -49,15 +43,15 @@ fn shift_head<T, F>(v: &mut [T], is_less: &mut F) // Read the first element into a stack-allocated variable. If a following comparison // operation panics, `hole` will get dropped and automatically write the element back // into the slice. - let mut tmp = NoDrop { value: ptr::read(v.get_unchecked(0)) }; + let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(0))); let mut hole = CopyOnDrop { - src: &mut tmp.value, + src: &mut *tmp, dest: v.get_unchecked_mut(1), }; ptr::copy_nonoverlapping(v.get_unchecked(1), v.get_unchecked_mut(0), 1); for i in 2..len { - if !is_less(v.get_unchecked(i), &tmp.value) { + if !is_less(v.get_unchecked(i), &*tmp) { break; } @@ -81,15 +75,15 @@ fn shift_tail<T, F>(v: &mut [T], is_less: &mut F) // Read the last element into a stack-allocated variable. If a following comparison // operation panics, `hole` will get dropped and automatically write the element back // into the slice. - let mut tmp = NoDrop { value: ptr::read(v.get_unchecked(len - 1)) }; + let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(len - 1))); let mut hole = CopyOnDrop { - src: &mut tmp.value, + src: &mut *tmp, dest: v.get_unchecked_mut(len - 2), }; ptr::copy_nonoverlapping(v.get_unchecked(len - 2), v.get_unchecked_mut(len - 1), 1); for i in (0..len-2).rev() { - if !is_less(&tmp.value, v.get_unchecked(i)) { + if !is_less(&*tmp, v.get_unchecked(i)) { break; } @@ -403,12 +397,12 @@ fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool) // Read the pivot into a stack-allocated variable for efficiency. If a following comparison // operation panics, the pivot will be automatically written back into the slice. - let mut tmp = NoDrop { value: unsafe { ptr::read(pivot) } }; + let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) }); let _pivot_guard = CopyOnDrop { - src: unsafe { &mut tmp.value }, + src: &mut *tmp, dest: pivot, }; - let pivot = unsafe { &tmp.value }; + let pivot = &*tmp; // Find the first pair of out-of-order elements. let mut l = 0; @@ -452,12 +446,12 @@ fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize // Read the pivot into a stack-allocated variable for efficiency. If a following comparison // operation panics, the pivot will be automatically written back into the slice. - let mut tmp = NoDrop { value: unsafe { ptr::read(pivot) } }; + let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) }); let _pivot_guard = CopyOnDrop { - src: unsafe { &mut tmp.value }, + src: &mut *tmp, dest: pivot, }; - let pivot = unsafe { &tmp.value }; + let pivot = &*tmp; // Now partition the slice. let mut l = 0; |
