diff options
| author | bors <bors@rust-lang.org> | 2023-02-11 15:08:30 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-02-11 15:08:30 +0000 |
| commit | 8dabf5da9e0318f8c324dc224ad49dc91472c2ec (patch) | |
| tree | 0a9bc43bba1ce13b519e1ee3bed52fae5dd9865c | |
| parent | 5b450244876154bc1bd134694398e80c12e00b5c (diff) | |
| parent | 6fcf1758feb63c7c70a40241f0ac8931a3ba46a9 (diff) | |
| download | rust-8dabf5da9e0318f8c324dc224ad49dc91472c2ec.tar.gz rust-8dabf5da9e0318f8c324dc224ad49dc91472c2ec.zip | |
Auto merge of #107167 - the8472:rawvec-simpler-layout, r=thomcc
simplify layout calculations in rawvec The use of `Layout::array` was introduced in #83706 which lead to a [perf regression](https://github.com/rust-lang/rust/pull/83706#issuecomment-1048377719). This PR basically reverts that change since rust currently only supports stride == size types, but to be on the safe side it leaves a const-assert there to make sure this gets caught if those assumptions ever change.
| -rw-r--r-- | library/alloc/src/raw_vec.rs | 17 | ||||
| -rw-r--r-- | tests/ui/hygiene/panic-location.run.stderr | 2 |
2 files changed, 13 insertions, 6 deletions
diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 5a10121bbbe..3751f2a2454 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -241,10 +241,15 @@ impl<T, A: Allocator> RawVec<T, A> { if T::IS_ZST || self.cap == 0 { None } else { - // We have an allocated chunk of memory, so we can bypass runtime - // checks to get our current layout. + // We could use Layout::array here which ensures the absence of isize and usize overflows + // and could hypothetically handle differences between stride and size, but this memory + // has already been allocated so we know it can't overflow and currently rust does not + // support such types. So we can do better by skipping some checks and avoid an unwrap. + let _: () = const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) }; unsafe { - let layout = Layout::array::<T>(self.cap).unwrap_unchecked(); + let align = mem::align_of::<T>(); + let size = mem::size_of::<T>().unchecked_mul(self.cap); + let layout = Layout::from_size_align_unchecked(size, align); Some((self.ptr.cast().into(), layout)) } } @@ -426,11 +431,13 @@ impl<T, A: Allocator> RawVec<T, A> { assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity"); let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) }; - + // See current_memory() why this assert is here + let _: () = const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) }; let ptr = unsafe { // `Layout::array` cannot overflow here because it would have // overflowed earlier when capacity was larger. - let new_layout = Layout::array::<T>(cap).unwrap_unchecked(); + let new_size = mem::size_of::<T>().unchecked_mul(cap); + let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); self.alloc .shrink(ptr, layout, new_layout) .map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })? diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index 0b23b1cc2f4..1c6a7b02f8e 100644 --- a/tests/ui/hygiene/panic-location.run.stderr +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -1,2 +1,2 @@ -thread 'main' panicked at 'capacity overflow', library/alloc/src/raw_vec.rs:518:5 +thread 'main' panicked at 'capacity overflow', library/alloc/src/raw_vec.rs:525:5 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace |
