Optimize Layout::array
.
The current implementation is much more conservative than it needs to
be, because it's dealing with the size and alignment of a given `T`,
which are more restricted than an arbitrary `Layout`.
For example, imagine a struct with a `u32` and a `u4`. You can safely
create a `Layout { size_: 5, align_: 4 }` by hand, but
`Layout:🆕:<T>` will give `Layout { size_: 8, align_: 4}`, where the
size already has padding that accounts for the alignment. (And the
existing `debug_assert_eq!` in `Layout::array` already demonstrates that
no additional padding is required.)
This commit is contained in:
parent
026edbb4ef
commit
f3bda74d36
1 changed files with 11 additions and 3 deletions
|
@ -405,9 +405,17 @@ impl Layout {
|
|||
#[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
|
||||
#[inline]
|
||||
pub fn array<T>(n: usize) -> Result<Self, LayoutError> {
|
||||
let (layout, offset) = Layout::new::<T>().repeat(n)?;
|
||||
debug_assert_eq!(offset, mem::size_of::<T>());
|
||||
Ok(layout.pad_to_align())
|
||||
let array_size = mem::size_of::<T>().checked_mul(n).ok_or(LayoutError)?;
|
||||
|
||||
// SAFETY:
|
||||
// - Size: `array_size` cannot be too big because `size_of::<T>()` must
|
||||
// be a multiple of `align_of::<T>()`. Therefore, `array_size`
|
||||
// rounded up to the nearest multiple of `align_of::<T>()` is just
|
||||
// `array_size`. And `array_size` cannot be too big because it was
|
||||
// just checked by the `checked_mul()`.
|
||||
// - Alignment: `align_of::<T>()` will always give an acceptable
|
||||
// (non-zero, power of two) alignment.
|
||||
Ok(unsafe { Layout::from_size_align_unchecked(array_size, mem::align_of::<T>()) })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue