@@ -241,10 +241,15 @@ impl<T, A: Allocator> RawVec<T, A> {
241
241
if T::IS_ZST || self.cap == 0 {
242
242
None
243
243
} else {
244
- // We have an allocated chunk of memory, so we can bypass runtime
245
- // checks to get our current layout.
244
+ // We could use Layout::array here which ensures the absence of isize and usize overflows
245
+ // and could hypothetically handle differences between stride and size, but this memory
246
+ // has already been allocated so we know it can't overflow and currently rust does not
247
+ // support such types. So we can do better by skipping some checks and avoid an unwrap.
248
+ let _: () = const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) };
246
249
unsafe {
247
- let layout = Layout::array::<T>(self.cap).unwrap_unchecked();
250
+ let align = mem::align_of::<T>();
251
+ let size = mem::size_of::<T>().unchecked_mul(self.cap);
252
+ let layout = Layout::from_size_align_unchecked(size, align);
248
253
Some((self.ptr.cast().into(), layout))
249
254
}
250
255
}
@@ -426,11 +431,13 @@ impl<T, A: Allocator> RawVec<T, A> {
426
431
assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity");
427
432
428
433
let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) };
429
-
434
+ // See current_memory() why this assert is here
435
+ let _: () = const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) };
430
436
let ptr = unsafe {
431
437
// `Layout::array` cannot overflow here because it would have
432
438
// overflowed earlier when capacity was larger.
433
- let new_layout = Layout::array::<T>(cap).unwrap_unchecked();
439
+ let new_size = mem::size_of::<T>().unchecked_mul(cap);
440
+ let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
434
441
self.alloc
435
442
.shrink(ptr, layout, new_layout)
436
443
.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })?
0 commit comments