use ManuallyDrop instead of forget inside collections
This commit changes some usage of mem::forget into mem::ManuallyDrop in some Vec, VecDeque, BTreeMap and Box methods. Before the commit, the generated IR for some of the methods was longer, and even after optimization, some unwinding artifacts were still present.
This commit is contained in:
parent
1b521f5773
commit
2b718e8d9c
|
@ -469,8 +469,8 @@ impl<T: ?Sized> Box<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn into_unique(b: Box<T>) -> Unique<T> {
|
pub fn into_unique(b: Box<T>) -> Unique<T> {
|
||||||
|
let b = mem::ManuallyDrop::new(b);
|
||||||
let mut unique = b.0;
|
let mut unique = b.0;
|
||||||
mem::forget(b);
|
|
||||||
// Box is kind-of a library type, but recognized as a "unique pointer" by
|
// Box is kind-of a library type, but recognized as a "unique pointer" by
|
||||||
// Stacked Borrows. This function here corresponds to "reborrowing to
|
// Stacked Borrows. This function here corresponds to "reborrowing to
|
||||||
// a raw pointer", but there is no actual reborrow here -- so
|
// a raw pointer", but there is no actual reborrow here -- so
|
||||||
|
|
|
@ -4,9 +4,10 @@ use core::fmt::Debug;
|
||||||
use core::hash::{Hash, Hasher};
|
use core::hash::{Hash, Hasher};
|
||||||
use core::iter::{FromIterator, FusedIterator, Peekable};
|
use core::iter::{FromIterator, FusedIterator, Peekable};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
use core::mem::{self, ManuallyDrop};
|
||||||
use core::ops::Bound::{Excluded, Included, Unbounded};
|
use core::ops::Bound::{Excluded, Included, Unbounded};
|
||||||
use core::ops::{Index, RangeBounds};
|
use core::ops::{Index, RangeBounds};
|
||||||
use core::{fmt, mem, ptr};
|
use core::{fmt, ptr};
|
||||||
|
|
||||||
use super::node::{self, marker, ForceResult::*, Handle, InsertResult::*, NodeRef};
|
use super::node::{self, marker, ForceResult::*, Handle, InsertResult::*, NodeRef};
|
||||||
use super::search::{self, SearchResult::*};
|
use super::search::{self, SearchResult::*};
|
||||||
|
@ -190,9 +191,9 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
|
||||||
// We can't destructure subtree directly
|
// We can't destructure subtree directly
|
||||||
// because BTreeMap implements Drop
|
// because BTreeMap implements Drop
|
||||||
let (subroot, sublength) = unsafe {
|
let (subroot, sublength) = unsafe {
|
||||||
|
let subtree = ManuallyDrop::new(subtree);
|
||||||
let root = ptr::read(&subtree.root);
|
let root = ptr::read(&subtree.root);
|
||||||
let length = subtree.length;
|
let length = subtree.length;
|
||||||
mem::forget(subtree);
|
|
||||||
(root, length)
|
(root, length)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1515,15 +1516,14 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
|
||||||
type IntoIter = IntoIter<K, V>;
|
type IntoIter = IntoIter<K, V>;
|
||||||
|
|
||||||
fn into_iter(self) -> IntoIter<K, V> {
|
fn into_iter(self) -> IntoIter<K, V> {
|
||||||
if self.root.is_none() {
|
let me = ManuallyDrop::new(self);
|
||||||
mem::forget(self);
|
if me.root.is_none() {
|
||||||
return IntoIter { front: None, back: None, length: 0 };
|
return IntoIter { front: None, back: None, length: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
let root1 = unsafe { unwrap_unchecked(ptr::read(&self.root)).into_ref() };
|
let root1 = unsafe { unwrap_unchecked(ptr::read(&me.root)).into_ref() };
|
||||||
let root2 = unsafe { unwrap_unchecked(ptr::read(&self.root)).into_ref() };
|
let root2 = unsafe { unwrap_unchecked(ptr::read(&me.root)).into_ref() };
|
||||||
let len = self.length;
|
let len = me.length;
|
||||||
mem::forget(self);
|
|
||||||
|
|
||||||
IntoIter {
|
IntoIter {
|
||||||
front: Some(root1.first_leaf_edge()),
|
front: Some(root1.first_leaf_edge()),
|
||||||
|
|
|
@ -12,7 +12,7 @@ use core::cmp::{self, Ordering};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::hash::{Hash, Hasher};
|
use core::hash::{Hash, Hasher};
|
||||||
use core::iter::{once, repeat_with, FromIterator, FusedIterator};
|
use core::iter::{once, repeat_with, FromIterator, FusedIterator};
|
||||||
use core::mem::{self, replace};
|
use core::mem::{self, replace, ManuallyDrop};
|
||||||
use core::ops::Bound::{Excluded, Included, Unbounded};
|
use core::ops::Bound::{Excluded, Included, Unbounded};
|
||||||
use core::ops::{Index, IndexMut, RangeBounds, Try};
|
use core::ops::{Index, IndexMut, RangeBounds, Try};
|
||||||
use core::ptr::{self, NonNull};
|
use core::ptr::{self, NonNull};
|
||||||
|
@ -2898,12 +2898,12 @@ impl<T> From<Vec<T>> for VecDeque<T> {
|
||||||
/// This avoids reallocating where possible, but the conditions for that are
|
/// This avoids reallocating where possible, but the conditions for that are
|
||||||
/// strict, and subject to change, and so shouldn't be relied upon unless the
|
/// strict, and subject to change, and so shouldn't be relied upon unless the
|
||||||
/// `Vec<T>` came from `From<VecDeque<T>>` and hasn't been reallocated.
|
/// `Vec<T>` came from `From<VecDeque<T>>` and hasn't been reallocated.
|
||||||
fn from(mut other: Vec<T>) -> Self {
|
fn from(other: Vec<T>) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let mut other = ManuallyDrop::new(other);
|
||||||
let other_buf = other.as_mut_ptr();
|
let other_buf = other.as_mut_ptr();
|
||||||
let mut buf = RawVec::from_raw_parts(other_buf, other.capacity());
|
let mut buf = RawVec::from_raw_parts(other_buf, other.capacity());
|
||||||
let len = other.len();
|
let len = other.len();
|
||||||
mem::forget(other);
|
|
||||||
|
|
||||||
// We need to extend the buf if it's not a power of two, too small
|
// We need to extend the buf if it's not a power of two, too small
|
||||||
// or doesn't have at least one free space
|
// or doesn't have at least one free space
|
||||||
|
@ -2955,6 +2955,7 @@ impl<T> From<VecDeque<T>> for Vec<T> {
|
||||||
other.make_contiguous();
|
other.make_contiguous();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let other = ManuallyDrop::new(other);
|
||||||
let buf = other.buf.ptr();
|
let buf = other.buf.ptr();
|
||||||
let len = other.len();
|
let len = other.len();
|
||||||
let cap = other.cap();
|
let cap = other.cap();
|
||||||
|
@ -2962,9 +2963,7 @@ impl<T> From<VecDeque<T>> for Vec<T> {
|
||||||
if other.head != 0 {
|
if other.head != 0 {
|
||||||
ptr::copy(buf.add(other.tail), buf, len);
|
ptr::copy(buf.add(other.tail), buf, len);
|
||||||
}
|
}
|
||||||
let out = Vec::from_raw_parts(buf, len, cap);
|
Vec::from_raw_parts(buf, len, cap)
|
||||||
mem::forget(other);
|
|
||||||
out
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
use core::alloc::MemoryBlock;
|
use core::alloc::MemoryBlock;
|
||||||
use core::cmp;
|
use core::cmp;
|
||||||
use core::mem::{self, MaybeUninit};
|
use core::mem::{self, ManuallyDrop, MaybeUninit};
|
||||||
use core::ops::Drop;
|
use core::ops::Drop;
|
||||||
use core::ptr::{NonNull, Unique};
|
use core::ptr::{NonNull, Unique};
|
||||||
use core::slice;
|
use core::slice;
|
||||||
|
@ -112,11 +112,10 @@ impl<T> RawVec<T, Global> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a `Box<[T]>` into a `RawVec<T>`.
|
/// Converts a `Box<[T]>` into a `RawVec<T>`.
|
||||||
pub fn from_box(mut slice: Box<[T]>) -> Self {
|
pub fn from_box(slice: Box<[T]>) -> Self {
|
||||||
unsafe {
|
unsafe {
|
||||||
let result = RawVec::from_raw_parts(slice.as_mut_ptr(), slice.len());
|
let mut slice = ManuallyDrop::new(slice);
|
||||||
mem::forget(slice);
|
RawVec::from_raw_parts(slice.as_mut_ptr(), slice.len())
|
||||||
result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -579,11 +578,10 @@ impl<T> RawVec<T, Global> {
|
||||||
"`len` must be smaller than or equal to `self.capacity()`"
|
"`len` must be smaller than or equal to `self.capacity()`"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let me = ManuallyDrop::new(self);
|
||||||
// NOTE: not calling `capacity()` here; actually using the real `cap` field!
|
// NOTE: not calling `capacity()` here; actually using the real `cap` field!
|
||||||
let slice = slice::from_raw_parts_mut(self.ptr() as *mut MaybeUninit<T>, len);
|
let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit<T>, len);
|
||||||
let output = Box::from_raw(slice);
|
Box::from_raw(slice)
|
||||||
mem::forget(self);
|
|
||||||
output
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ use core::hash::{self, Hash};
|
||||||
use core::intrinsics::{arith_offset, assume};
|
use core::intrinsics::{arith_offset, assume};
|
||||||
use core::iter::{FromIterator, FusedIterator, TrustedLen};
|
use core::iter::{FromIterator, FusedIterator, TrustedLen};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::mem;
|
use core::mem::{self, ManuallyDrop};
|
||||||
use core::ops::Bound::{Excluded, Included, Unbounded};
|
use core::ops::Bound::{Excluded, Included, Unbounded};
|
||||||
use core::ops::{self, Index, IndexMut, RangeBounds};
|
use core::ops::{self, Index, IndexMut, RangeBounds};
|
||||||
use core::ptr::{self, NonNull};
|
use core::ptr::{self, NonNull};
|
||||||
|
@ -392,7 +392,7 @@ impl<T> Vec<T> {
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
|
#[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
|
||||||
pub fn into_raw_parts(self) -> (*mut T, usize, usize) {
|
pub fn into_raw_parts(self) -> (*mut T, usize, usize) {
|
||||||
let mut me = mem::ManuallyDrop::new(self);
|
let mut me = ManuallyDrop::new(self);
|
||||||
(me.as_mut_ptr(), me.len(), me.capacity())
|
(me.as_mut_ptr(), me.len(), me.capacity())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,9 +678,9 @@ impl<T> Vec<T> {
|
||||||
pub fn into_boxed_slice(mut self) -> Box<[T]> {
|
pub fn into_boxed_slice(mut self) -> Box<[T]> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.shrink_to_fit();
|
self.shrink_to_fit();
|
||||||
let buf = ptr::read(&self.buf);
|
let me = ManuallyDrop::new(self);
|
||||||
let len = self.len();
|
let buf = ptr::read(&me.buf);
|
||||||
mem::forget(self);
|
let len = me.len();
|
||||||
buf.into_box(len).assume_init()
|
buf.into_box(len).assume_init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1949,16 +1949,16 @@ impl<T> IntoIterator for Vec<T> {
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_iter(mut self) -> IntoIter<T> {
|
fn into_iter(self) -> IntoIter<T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let begin = self.as_mut_ptr();
|
let mut me = ManuallyDrop::new(self);
|
||||||
|
let begin = me.as_mut_ptr();
|
||||||
let end = if mem::size_of::<T>() == 0 {
|
let end = if mem::size_of::<T>() == 0 {
|
||||||
arith_offset(begin as *const i8, self.len() as isize) as *const T
|
arith_offset(begin as *const i8, me.len() as isize) as *const T
|
||||||
} else {
|
} else {
|
||||||
begin.add(self.len()) as *const T
|
begin.add(me.len()) as *const T
|
||||||
};
|
};
|
||||||
let cap = self.buf.capacity();
|
let cap = me.buf.capacity();
|
||||||
mem::forget(self);
|
|
||||||
IntoIter {
|
IntoIter {
|
||||||
buf: NonNull::new_unchecked(begin),
|
buf: NonNull::new_unchecked(begin),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
|
@ -2081,9 +2081,8 @@ impl<T> SpecExtend<T, IntoIter<T>> for Vec<T> {
|
||||||
// has not been advanced at all.
|
// has not been advanced at all.
|
||||||
if iterator.buf.as_ptr() as *const _ == iterator.ptr {
|
if iterator.buf.as_ptr() as *const _ == iterator.ptr {
|
||||||
unsafe {
|
unsafe {
|
||||||
let vec = Vec::from_raw_parts(iterator.buf.as_ptr(), iterator.len(), iterator.cap);
|
let it = ManuallyDrop::new(iterator);
|
||||||
mem::forget(iterator);
|
Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap)
|
||||||
vec
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut vector = Vec::new();
|
let mut vector = Vec::new();
|
||||||
|
|
Loading…
Reference in New Issue