Skip to content

Commit 2b718e8

Browse files
committed
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.
1 parent 1b521f5 commit 2b718e8

File tree

5 files changed

+34
-38
lines changed

5 files changed

+34
-38
lines changed

src/liballoc/boxed.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -469,8 +469,8 @@ impl<T: ?Sized> Box<T> {
469469
#[inline]
470470
#[doc(hidden)]
471471
pub fn into_unique(b: Box<T>) -> Unique<T> {
472+
let b = mem::ManuallyDrop::new(b);
472473
let mut unique = b.0;
473-
mem::forget(b);
474474
// Box is kind-of a library type, but recognized as a "unique pointer" by
475475
// Stacked Borrows. This function here corresponds to "reborrowing to
476476
// a raw pointer", but there is no actual reborrow here -- so

src/liballoc/collections/btree/map.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ use core::fmt::Debug;
44
use core::hash::{Hash, Hasher};
55
use core::iter::{FromIterator, FusedIterator, Peekable};
66
use core::marker::PhantomData;
7+
use core::mem::{self, ManuallyDrop};
78
use core::ops::Bound::{Excluded, Included, Unbounded};
89
use core::ops::{Index, RangeBounds};
9-
use core::{fmt, mem, ptr};
10+
use core::{fmt, ptr};
1011

1112
use super::node::{self, marker, ForceResult::*, Handle, InsertResult::*, NodeRef};
1213
use super::search::{self, SearchResult::*};
@@ -190,9 +191,9 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
190191
// We can't destructure subtree directly
191192
// because BTreeMap implements Drop
192193
let (subroot, sublength) = unsafe {
194+
let subtree = ManuallyDrop::new(subtree);
193195
let root = ptr::read(&subtree.root);
194196
let length = subtree.length;
195-
mem::forget(subtree);
196197
(root, length)
197198
};
198199

@@ -1515,15 +1516,14 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
15151516
type IntoIter = IntoIter<K, V>;
15161517

15171518
fn into_iter(self) -> IntoIter<K, V> {
1518-
if self.root.is_none() {
1519-
mem::forget(self);
1519+
let me = ManuallyDrop::new(self);
1520+
if me.root.is_none() {
15201521
return IntoIter { front: None, back: None, length: 0 };
15211522
}
15221523

1523-
let root1 = unsafe { unwrap_unchecked(ptr::read(&self.root)).into_ref() };
1524-
let root2 = unsafe { unwrap_unchecked(ptr::read(&self.root)).into_ref() };
1525-
let len = self.length;
1526-
mem::forget(self);
1524+
let root1 = unsafe { unwrap_unchecked(ptr::read(&me.root)).into_ref() };
1525+
let root2 = unsafe { unwrap_unchecked(ptr::read(&me.root)).into_ref() };
1526+
let len = me.length;
15271527

15281528
IntoIter {
15291529
front: Some(root1.first_leaf_edge()),

src/liballoc/collections/vec_deque.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use core::cmp::{self, Ordering};
1212
use core::fmt;
1313
use core::hash::{Hash, Hasher};
1414
use core::iter::{once, repeat_with, FromIterator, FusedIterator};
15-
use core::mem::{self, replace};
15+
use core::mem::{self, replace, ManuallyDrop};
1616
use core::ops::Bound::{Excluded, Included, Unbounded};
1717
use core::ops::{Index, IndexMut, RangeBounds, Try};
1818
use core::ptr::{self, NonNull};
@@ -2898,12 +2898,12 @@ impl<T> From<Vec<T>> for VecDeque<T> {
28982898
/// This avoids reallocating where possible, but the conditions for that are
28992899
/// strict, and subject to change, and so shouldn't be relied upon unless the
29002900
/// `Vec<T>` came from `From<VecDeque<T>>` and hasn't been reallocated.
2901-
fn from(mut other: Vec<T>) -> Self {
2901+
fn from(other: Vec<T>) -> Self {
29022902
unsafe {
2903+
let mut other = ManuallyDrop::new(other);
29032904
let other_buf = other.as_mut_ptr();
29042905
let mut buf = RawVec::from_raw_parts(other_buf, other.capacity());
29052906
let len = other.len();
2906-
mem::forget(other);
29072907

29082908
// We need to extend the buf if it's not a power of two, too small
29092909
// or doesn't have at least one free space
@@ -2955,16 +2955,15 @@ impl<T> From<VecDeque<T>> for Vec<T> {
29552955
other.make_contiguous();
29562956

29572957
unsafe {
2958+
let other = ManuallyDrop::new(other);
29582959
let buf = other.buf.ptr();
29592960
let len = other.len();
29602961
let cap = other.cap();
29612962

29622963
if other.head != 0 {
29632964
ptr::copy(buf.add(other.tail), buf, len);
29642965
}
2965-
let out = Vec::from_raw_parts(buf, len, cap);
2966-
mem::forget(other);
2967-
out
2966+
Vec::from_raw_parts(buf, len, cap)
29682967
}
29692968
}
29702969
}

src/liballoc/raw_vec.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use core::alloc::MemoryBlock;
55
use core::cmp;
6-
use core::mem::{self, MaybeUninit};
6+
use core::mem::{self, ManuallyDrop, MaybeUninit};
77
use core::ops::Drop;
88
use core::ptr::{NonNull, Unique};
99
use core::slice;
@@ -112,11 +112,10 @@ impl<T> RawVec<T, Global> {
112112
}
113113

114114
/// Converts a `Box<[T]>` into a `RawVec<T>`.
115-
pub fn from_box(mut slice: Box<[T]>) -> Self {
115+
pub fn from_box(slice: Box<[T]>) -> Self {
116116
unsafe {
117-
let result = RawVec::from_raw_parts(slice.as_mut_ptr(), slice.len());
118-
mem::forget(slice);
119-
result
117+
let mut slice = ManuallyDrop::new(slice);
118+
RawVec::from_raw_parts(slice.as_mut_ptr(), slice.len())
120119
}
121120
}
122121
}
@@ -579,11 +578,10 @@ impl<T> RawVec<T, Global> {
579578
"`len` must be smaller than or equal to `self.capacity()`"
580579
);
581580

581+
let me = ManuallyDrop::new(self);
582582
// NOTE: not calling `capacity()` here; actually using the real `cap` field!
583-
let slice = slice::from_raw_parts_mut(self.ptr() as *mut MaybeUninit<T>, len);
584-
let output = Box::from_raw(slice);
585-
mem::forget(self);
586-
output
583+
let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit<T>, len);
584+
Box::from_raw(slice)
587585
}
588586
}
589587

src/liballoc/vec.rs

+13-14
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ use core::hash::{self, Hash};
6666
use core::intrinsics::{arith_offset, assume};
6767
use core::iter::{FromIterator, FusedIterator, TrustedLen};
6868
use core::marker::PhantomData;
69-
use core::mem;
69+
use core::mem::{self, ManuallyDrop};
7070
use core::ops::Bound::{Excluded, Included, Unbounded};
7171
use core::ops::{self, Index, IndexMut, RangeBounds};
7272
use core::ptr::{self, NonNull};
@@ -392,7 +392,7 @@ impl<T> Vec<T> {
392392
/// ```
393393
#[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
394394
pub fn into_raw_parts(self) -> (*mut T, usize, usize) {
395-
let mut me = mem::ManuallyDrop::new(self);
395+
let mut me = ManuallyDrop::new(self);
396396
(me.as_mut_ptr(), me.len(), me.capacity())
397397
}
398398

@@ -678,9 +678,9 @@ impl<T> Vec<T> {
678678
pub fn into_boxed_slice(mut self) -> Box<[T]> {
679679
unsafe {
680680
self.shrink_to_fit();
681-
let buf = ptr::read(&self.buf);
682-
let len = self.len();
683-
mem::forget(self);
681+
let me = ManuallyDrop::new(self);
682+
let buf = ptr::read(&me.buf);
683+
let len = me.len();
684684
buf.into_box(len).assume_init()
685685
}
686686
}
@@ -1949,16 +1949,16 @@ impl<T> IntoIterator for Vec<T> {
19491949
/// }
19501950
/// ```
19511951
#[inline]
1952-
fn into_iter(mut self) -> IntoIter<T> {
1952+
fn into_iter(self) -> IntoIter<T> {
19531953
unsafe {
1954-
let begin = self.as_mut_ptr();
1954+
let mut me = ManuallyDrop::new(self);
1955+
let begin = me.as_mut_ptr();
19551956
let end = if mem::size_of::<T>() == 0 {
1956-
arith_offset(begin as *const i8, self.len() as isize) as *const T
1957+
arith_offset(begin as *const i8, me.len() as isize) as *const T
19571958
} else {
1958-
begin.add(self.len()) as *const T
1959+
begin.add(me.len()) as *const T
19591960
};
1960-
let cap = self.buf.capacity();
1961-
mem::forget(self);
1961+
let cap = me.buf.capacity();
19621962
IntoIter {
19631963
buf: NonNull::new_unchecked(begin),
19641964
phantom: PhantomData,
@@ -2081,9 +2081,8 @@ impl<T> SpecExtend<T, IntoIter<T>> for Vec<T> {
20812081
// has not been advanced at all.
20822082
if iterator.buf.as_ptr() as *const _ == iterator.ptr {
20832083
unsafe {
2084-
let vec = Vec::from_raw_parts(iterator.buf.as_ptr(), iterator.len(), iterator.cap);
2085-
mem::forget(iterator);
2086-
vec
2084+
let it = ManuallyDrop::new(iterator);
2085+
Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap)
20872086
}
20882087
} else {
20892088
let mut vector = Vec::new();

0 commit comments

Comments
 (0)