diff options
| author | The 8472 <git@infinite-source.de> | 2023-05-29 13:04:26 +0200 |
|---|---|---|
| committer | The 8472 <git@infinite-source.de> | 2023-09-03 19:59:47 +0200 |
| commit | 072b51cbb5b4ee39ae433b5f92a5952054e6caf3 (patch) | |
| tree | 1928ec651000aecedab037303baecc4d04070bcb | |
| parent | c98070d522d8d12e61219f268ac377aceda30e92 (diff) | |
| download | rust-072b51cbb5b4ee39ae433b5f92a5952054e6caf3.tar.gz rust-072b51cbb5b4ee39ae433b5f92a5952054e6caf3.zip | |
unchecked layout calculations when shrinking during in-place collect
Reduces the amount of emitted IR. RawVec has similar optimizations
| -rw-r--r-- | library/alloc/src/vec/in_place_collect.rs | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index 1f03f0d19ec..e4f96fd7640 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -267,10 +267,20 @@ where { let alloc = Global; unsafe { - let new_layout = Layout::array::<T>(dst_cap).unwrap(); + // The old allocation exists, therefore it must have a valid layout. + let src_align = mem::align_of::<I::Src>(); + let src_size = mem::size_of::<I::Src>().unchecked_mul(src_cap); + let old_layout = Layout::from_size_align_unchecked(src_size, src_align); + + // The must be equal or smaller for in-place iteration to be possible + // therefore the new layout must be ≤ the old one and therefore valid. + let dst_align = mem::align_of::<T>(); + let dst_size = mem::size_of::<T>().unchecked_mul(dst_cap); + let new_layout = Layout::from_size_align_unchecked(dst_size, dst_align); + let result = alloc.shrink( NonNull::new_unchecked(dst_buf as *mut u8), - Layout::array::<I::Src>(src_cap).unwrap(), + old_layout, new_layout, ); let Ok(reallocated) = result else { handle_alloc_error(new_layout) }; |
