Skip to content

Commit 40fa827

Browse files
committed
Stop using Vec as an allocator
1 parent 6c76c41 commit 40fa827

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

lib.rs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
//!
4141
//! When this feature is enabled, `SmallVec` works with any arrays of any size, not just a fixed
4242
//! list of sizes.
43-
//!
43+
//!
4444
//! ### `specialization`
4545
//!
4646
//! **This feature is unstable and requires a nightly build of the Rust toolchain.**
@@ -71,6 +71,7 @@ pub extern crate alloc;
7171
#[cfg(any(test, feature = "write"))]
7272
extern crate std;
7373

74+
use alloc::alloc::{Layout, LayoutErr};
7475
use alloc::boxed::Box;
7576
use alloc::{vec, vec::Vec};
7677
use core::borrow::{Borrow, BorrowMut};
@@ -200,9 +201,31 @@ impl<T: Clone> ExtendFromSlice<T> for Vec<T> {
200201
}
201202
}
202203

204+
#[derive(Debug)]
205+
enum CollectionAllocErr {
206+
CapacityOverflow,
207+
}
208+
209+
impl From<LayoutErr> for CollectionAllocErr {
210+
fn from(_: LayoutErr) -> Self {
211+
CollectionAllocErr::CapacityOverflow
212+
}
213+
}
214+
215+
/// FIXME: use `Layout::array` when we require a Rust version where it’s stable
216+
/// https://github.com/rust-lang/rust/issues/55724
217+
fn layout_array<T>(n: usize) -> Result<Layout, CollectionAllocErr> {
218+
let size = mem::size_of::<T>().checked_mul(n)
219+
.ok_or(CollectionAllocErr::CapacityOverflow)?;
220+
let align = mem::align_of::<T>();
221+
Layout::from_size_align(size, align)
222+
.map_err(|_| CollectionAllocErr::CapacityOverflow)
223+
}
224+
203225
unsafe fn deallocate<T>(ptr: *mut T, capacity: usize) {
204-
let _vec: Vec<T> = Vec::from_raw_parts(ptr, 0, capacity);
205-
// Let it drop.
226+
// This unwrap should succeed since the same did when allocating.
227+
let layout = layout_array::<T>(capacity).unwrap();
228+
alloc::alloc::dealloc(ptr as *mut u8, layout)
206229
}
207230

208231
/// An iterator that removes the items from a `SmallVec` and yields them by value.
@@ -705,9 +728,12 @@ impl<A: Array> SmallVec<A> {
705728
ptr::copy_nonoverlapping(ptr, self.data.inline_mut(), len);
706729
self.capacity = len;
707730
} else if new_cap != cap {
708-
let mut vec = Vec::with_capacity(new_cap);
709-
let new_alloc = vec.as_mut_ptr();
710-
mem::forget(vec);
731+
// Panic on overflow
732+
let layout = layout_array::<A::Item>(new_cap).unwrap();
733+
let new_alloc = NonNull::new(alloc::alloc::alloc(layout))
734+
.unwrap_or_else(|| alloc::alloc::handle_alloc_error(layout))
735+
.cast()
736+
.as_ptr();
711737
ptr::copy_nonoverlapping(ptr, new_alloc, len);
712738
self.data = SmallVecData::from_heap(new_alloc, len);
713739
self.capacity = new_cap;

0 commit comments

Comments
 (0)