Skip to content

Commit ea5f7e1

Browse files
author
Thom Chiovoloni
committed
Use MaybeUninit for storage of inline items.
This includes two breaking changes, in addition to the fact that it will require a MSRV bump: 1. The functions on the `Array` trait `ptr` and `ptr_mut` have been removed. Because these took a `&self`/`&mut self` argument, there's no way for us to call them when we only have a `MaybeUninit<A>`. Now, we just use the memory of the object directly. This limits the flexibility of custom implementations of `Array`, (they can no longer return pointers to values other than themselves) but I imagine this is very rare and was probably broken somehow to begin with. Anybody who does this will get a compile error. 2. `from_buf_and_len_unchecked` now takes a MaybeUninit<A>, so that callers have the option of only partially initializing the array.
1 parent 3ee6d1e commit ea5f7e1

File tree

1 file changed

+42
-45
lines changed

1 file changed

+42
-45
lines changed

lib.rs

+42-45
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ use std::fmt;
5656
use std::hash::{Hash, Hasher};
5757
use std::iter::{IntoIterator, FromIterator, repeat};
5858
use std::mem;
59-
use std::mem::ManuallyDrop;
59+
use std::mem::MaybeUninit;
6060
use std::ops;
6161
use std::ptr;
6262
use std::slice;
@@ -275,26 +275,26 @@ impl<'a, T: 'a> Drop for Drain<'a,T> {
275275

276276
#[cfg(feature = "union")]
277277
union SmallVecData<A: Array> {
278-
inline: ManuallyDrop<A>,
278+
inline: MaybeUninit<A>,
279279
heap: (*mut A::Item, usize),
280280
}
281281

282282
#[cfg(feature = "union")]
283283
impl<A: Array> SmallVecData<A> {
284284
#[inline]
285-
unsafe fn inline(&self) -> &A {
286-
&self.inline
285+
unsafe fn inline(&self) -> *const A::Item {
286+
self.inline.as_ptr() as *const A::Item
287287
}
288288
#[inline]
289-
unsafe fn inline_mut(&mut self) -> &mut A {
290-
&mut self.inline
289+
unsafe fn inline_mut(&mut self) -> *mut A::Item {
290+
self.inline.as_mut_ptr() as *mut A::Item
291291
}
292292
#[inline]
293-
fn from_inline(inline: A) -> SmallVecData<A> {
294-
SmallVecData { inline: ManuallyDrop::new(inline) }
293+
fn from_inline(inline: MaybeUninit<A>) -> SmallVecData<A> {
294+
SmallVecData { inline }
295295
}
296296
#[inline]
297-
unsafe fn into_inline(self) -> A { ManuallyDrop::into_inner(self.inline) }
297+
unsafe fn into_inline(self) -> MaybeUninit<A> { self.inline }
298298
#[inline]
299299
unsafe fn heap(&self) -> (*mut A::Item, usize) {
300300
self.heap
@@ -311,34 +311,34 @@ impl<A: Array> SmallVecData<A> {
311311

312312
#[cfg(not(feature = "union"))]
313313
enum SmallVecData<A: Array> {
314-
Inline(ManuallyDrop<A>),
314+
Inline(MaybeUninit<A>),
315315
Heap((*mut A::Item, usize)),
316316
}
317317

318318
#[cfg(not(feature = "union"))]
319319
impl<A: Array> SmallVecData<A> {
320320
#[inline]
321-
unsafe fn inline(&self) -> &A {
321+
unsafe fn inline(&self) -> *const A::Item {
322322
match *self {
323-
SmallVecData::Inline(ref a) => a,
323+
SmallVecData::Inline(ref a) => a.as_ptr() as *const A::Item,
324324
_ => debug_unreachable!(),
325325
}
326326
}
327327
#[inline]
328-
unsafe fn inline_mut(&mut self) -> &mut A {
328+
unsafe fn inline_mut(&mut self) -> *mut A::Item {
329329
match *self {
330-
SmallVecData::Inline(ref mut a) => a,
330+
SmallVecData::Inline(ref mut a) => a.as_mut_ptr() as *mut A::Item,
331331
_ => debug_unreachable!(),
332332
}
333333
}
334334
#[inline]
335-
fn from_inline(inline: A) -> SmallVecData<A> {
336-
SmallVecData::Inline(ManuallyDrop::new(inline))
335+
fn from_inline(inline: MaybeUninit<A>) -> SmallVecData<A> {
336+
SmallVecData::Inline(inline)
337337
}
338338
#[inline]
339-
unsafe fn into_inline(self) -> A {
339+
unsafe fn into_inline(self) -> MaybeUninit<A> {
340340
match self {
341-
SmallVecData::Inline(a) => ManuallyDrop::into_inner(a),
341+
SmallVecData::Inline(a) => a,
342342
_ => debug_unreachable!(),
343343
}
344344
}
@@ -403,11 +403,13 @@ impl<A: Array> SmallVec<A> {
403403
/// Construct an empty vector
404404
#[inline]
405405
pub fn new() -> SmallVec<A> {
406-
unsafe {
407-
SmallVec {
408-
capacity: 0,
409-
data: SmallVecData::from_inline(mem::uninitialized()),
410-
}
406+
debug_assert!(
407+
(mem::size_of::<A>() == A::size() * mem::size_of::<A::Item>()) &&
408+
(mem::align_of::<A>() >= mem::align_of::<A::Item>())
409+
);
410+
SmallVec {
411+
capacity: 0,
412+
data: SmallVecData::from_inline(MaybeUninit::uninit()),
411413
}
412414
}
413415

@@ -447,10 +449,10 @@ impl<A: Array> SmallVec<A> {
447449
pub fn from_vec(mut vec: Vec<A::Item>) -> SmallVec<A> {
448450
if vec.capacity() <= A::size() {
449451
unsafe {
450-
let mut data = SmallVecData::<A>::from_inline(mem::uninitialized());
452+
let mut data = SmallVecData::<A>::from_inline(MaybeUninit::uninit());
451453
let len = vec.len();
452454
vec.set_len(0);
453-
ptr::copy_nonoverlapping(vec.as_ptr(), data.inline_mut().ptr_mut(), len);
455+
ptr::copy_nonoverlapping(vec.as_ptr(), data.inline_mut(), len);
454456

455457
SmallVec {
456458
capacity: len,
@@ -483,7 +485,7 @@ impl<A: Array> SmallVec<A> {
483485
pub fn from_buf(buf: A) -> SmallVec<A> {
484486
SmallVec {
485487
capacity: A::size(),
486-
data: SmallVecData::from_inline(buf),
488+
data: SmallVecData::from_inline(MaybeUninit::new(buf)),
487489
}
488490
}
489491

@@ -502,7 +504,7 @@ impl<A: Array> SmallVec<A> {
502504
#[inline]
503505
pub fn from_buf_and_len(buf: A, len: usize) -> SmallVec<A> {
504506
assert!(len <= A::size());
505-
unsafe { SmallVec::from_buf_and_len_unchecked(buf, len) }
507+
unsafe { SmallVec::from_buf_and_len_unchecked(MaybeUninit::new(buf), len) }
506508
}
507509

508510
/// Constructs a new `SmallVec` on the stack from an `A` without
@@ -511,16 +513,17 @@ impl<A: Array> SmallVec<A> {
511513
///
512514
/// ```rust
513515
/// use smallvec::SmallVec;
516+
/// use std::mem::MaybeUninit;
514517
///
515518
/// let buf = [1, 2, 3, 4, 5, 0, 0, 0];
516519
/// let small_vec: SmallVec<_> = unsafe {
517-
/// SmallVec::from_buf_and_len_unchecked(buf, 5)
520+
/// SmallVec::from_buf_and_len_unchecked(MaybeUninit::new(buf), 5)
518521
/// };
519522
///
520523
/// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]);
521524
/// ```
522525
#[inline]
523-
pub unsafe fn from_buf_and_len_unchecked(buf: A, len: usize) -> SmallVec<A> {
526+
pub unsafe fn from_buf_and_len_unchecked(buf: MaybeUninit<A>, len: usize) -> SmallVec<A> {
524527
SmallVec {
525528
capacity: len,
526529
data: SmallVecData::from_inline(buf),
@@ -571,7 +574,7 @@ impl<A: Array> SmallVec<A> {
571574
let (ptr, len) = self.data.heap();
572575
(ptr, len, self.capacity)
573576
} else {
574-
(self.data.inline().ptr(), self.capacity, A::size())
577+
(self.data.inline(), self.capacity, A::size())
575578
}
576579
}
577580
}
@@ -584,7 +587,7 @@ impl<A: Array> SmallVec<A> {
584587
let &mut (ptr, ref mut len_ptr) = self.data.heap_mut();
585588
(ptr, len_ptr, self.capacity)
586589
} else {
587-
(self.data.inline_mut().ptr_mut(), &mut self.capacity, A::size())
590+
(self.data.inline_mut(), &mut self.capacity, A::size())
588591
}
589592
}
590593
}
@@ -651,8 +654,8 @@ impl<A: Array> SmallVec<A> {
651654
if unspilled {
652655
return;
653656
}
654-
self.data = SmallVecData::from_inline(mem::uninitialized());
655-
ptr::copy_nonoverlapping(ptr, self.data.inline_mut().ptr_mut(), len);
657+
self.data = SmallVecData::from_inline(MaybeUninit::uninit());
658+
ptr::copy_nonoverlapping(ptr, self.data.inline_mut(), len);
656659
self.capacity = len;
657660
} else if new_cap != cap {
658661
let mut vec = Vec::with_capacity(new_cap);
@@ -717,8 +720,8 @@ impl<A: Array> SmallVec<A> {
717720
if self.inline_size() >= len {
718721
unsafe {
719722
let (ptr, len) = self.data.heap();
720-
self.data = SmallVecData::from_inline(mem::uninitialized());
721-
ptr::copy_nonoverlapping(ptr, self.data.inline_mut().ptr_mut(), len);
723+
self.data = SmallVecData::from_inline(MaybeUninit::uninit());
724+
ptr::copy_nonoverlapping(ptr, self.data.inline_mut(), len);
722725
deallocate(ptr, self.capacity);
723726
self.capacity = len;
724727
}
@@ -883,7 +886,7 @@ impl<A: Array> SmallVec<A> {
883886
unsafe {
884887
let data = ptr::read(&self.data);
885888
mem::forget(self);
886-
Ok(data.into_inline())
889+
Ok(data.into_inline().assume_init())
887890
}
888891
}
889892
}
@@ -1041,8 +1044,8 @@ impl<A: Array> SmallVec<A> where A::Item: Copy {
10411044
SmallVec {
10421045
capacity: len,
10431046
data: SmallVecData::from_inline(unsafe {
1044-
let mut data: A = mem::uninitialized();
1045-
ptr::copy_nonoverlapping(slice.as_ptr(), data.ptr_mut(), len);
1047+
let mut data: MaybeUninit<A> = MaybeUninit::uninit();
1048+
ptr::copy_nonoverlapping(slice.as_ptr(), data.as_mut_ptr() as *mut A::Item, len);
10461049
data
10471050
})
10481051
}
@@ -1543,10 +1546,6 @@ pub unsafe trait Array {
15431546
type Item;
15441547
/// Returns the number of items the array can hold.
15451548
fn size() -> usize;
1546-
/// Returns a pointer to the first element of the array.
1547-
fn ptr(&self) -> *const Self::Item;
1548-
/// Returns a mutable pointer to the first element of the array.
1549-
fn ptr_mut(&mut self) -> *mut Self::Item;
15501549
}
15511550

15521551
/// Set the length of the vec when the `SetLenOnDrop` value goes out of scope.
@@ -1587,8 +1586,6 @@ macro_rules! impl_array(
15871586
unsafe impl<T> Array for [T; $size] {
15881587
type Item = T;
15891588
fn size() -> usize { $size }
1590-
fn ptr(&self) -> *const T { self.as_ptr() }
1591-
fn ptr_mut(&mut self) -> *mut T { self.as_mut_ptr() }
15921589
}
15931590
)+
15941591
}
@@ -1889,7 +1886,7 @@ mod tests {
18891886
assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
18901887
}
18911888

1892-
#[cfg(feature = "std")]
1889+
#[cfg(all(feature = "std", not(miri)))] // Miri currently does not support unwinding
18931890
#[test]
18941891
// https://github.com/servo/rust-smallvec/issues/96
18951892
fn test_insert_many_panic() {

0 commit comments

Comments
 (0)