|
40 | 40 | //!
|
41 | 41 | //! When this feature is enabled, `SmallVec` works with any arrays of any size, not just a fixed
|
42 | 42 | //! list of sizes.
|
43 |
| -//! |
| 43 | +//! |
44 | 44 | //! ### `specialization`
|
45 | 45 | //!
|
46 | 46 | //! **This feature is unstable and requires a nightly build of the Rust toolchain.**
|
@@ -71,6 +71,7 @@ pub extern crate alloc;
|
71 | 71 | #[cfg(any(test, feature = "write"))]
|
72 | 72 | extern crate std;
|
73 | 73 |
|
| 74 | +use alloc::alloc::{Layout, LayoutErr}; |
74 | 75 | use alloc::boxed::Box;
|
75 | 76 | use alloc::{vec, vec::Vec};
|
76 | 77 | use core::borrow::{Borrow, BorrowMut};
|
@@ -200,9 +201,31 @@ impl<T: Clone> ExtendFromSlice<T> for Vec<T> {
|
200 | 201 | }
|
201 | 202 | }
|
202 | 203 |
|
| 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 | + |
203 | 225 | 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) |
206 | 229 | }
|
207 | 230 |
|
208 | 231 | /// An iterator that removes the items from a `SmallVec` and yields them by value.
|
@@ -705,9 +728,12 @@ impl<A: Array> SmallVec<A> {
|
705 | 728 | ptr::copy_nonoverlapping(ptr, self.data.inline_mut(), len);
|
706 | 729 | self.capacity = len;
|
707 | 730 | } 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(); |
711 | 737 | ptr::copy_nonoverlapping(ptr, new_alloc, len);
|
712 | 738 | self.data = SmallVecData::from_heap(new_alloc, len);
|
713 | 739 | self.capacity = new_cap;
|
|
0 commit comments