layout.rs - source
Description: Source of the Rust file `library/core/src/alloc/layout.rs`.

#
core/alloc/
layout.rs

    1// Seemingly inconsequential code changes to this file can lead to measurable
    2// performance impact on compilation times, due at least in part to the fact
    3// that the layout code gets called from many instantiations of the various
    4// collections, resulting in having to optimize down excess IR multiple times.
    5// Your performance intuition is useless. Run perf.
    6
    7use crate::error::Error;
    8use crate::intrinsics::{unchecked_add, unchecked_mul, unchecked_sub};
    9use crate::mem::SizedTypeProperties;
    10use crate::ptr::{Alignment, NonNull};
    11use crate::{assert_unsafe_precondition, fmt, mem};
    12
    13/// Layout of a block of memory.
    14///
    15/// An instance of `Layout` describes a particular layout of memory.
    16/// You build a `Layout` up as an input to give to an allocator.
    17///
    18/// All layouts have an associated size and a power-of-two alignment. The size, when rounded up to
    19/// the nearest multiple of `align`, does not overflow `isize` (i.e., the rounded value will always be
    20/// less than or equal to `isize::MAX`).
    21///
    22/// (Note that layouts are *not* required to have non-zero size,
    23/// even though `GlobalAlloc` requires that all memory requests
    24/// be non-zero in size. A caller must either ensure that conditions
    25/// like this are met, use specific allocators with looser
    26/// requirements, or use the more lenient `Allocator` interface.)
    27#[stable(feature = "alloc_layout", since = "1.28.0")]
    28#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
    29#[lang = "alloc_layout"]
    30pub struct Layout {
    31    // size of the requested block of memory, measured in bytes.
    32    size: usize,
    33
    34    // alignment of the requested block of memory, measured in bytes.
    35    // we ensure that this is always a power-of-two, because API's
    36    // like `posix_memalign` require it and it is a reasonable
    37    // constraint to impose on Layout constructors.
    38    //
    39    // (However, we do not analogously require `align >= sizeof(void*)`,
    40    //  even though that is *also* a requirement of `posix_memalign`.)
    41    align: Alignment,
    42}
    43
    44impl Layout {
    45    /// Constructs a `Layout` from a given `size` and `align`,
    46    /// or returns `LayoutError` if any of the following conditions
    47    /// are not met:
    48    ///
    49    /// * `align` must not be zero,
    50    ///
    51    /// * `align` must be a power of two,
    52    ///
    53    /// * `size`, when rounded up to the nearest multiple of `align`,
    54    ///   must not overflow `isize` (i.e., the rounded value must be
    55    ///   less than or equal to `isize::MAX`).
    56    #[stable(feature = "alloc_layout", since = "1.28.0")]
    57    #[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
    58    #[inline]
    59    pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutError> {
    60        if Layout::is_size_align_valid(size, align) {
    61            // SAFETY: Layout::is_size_align_valid checks the preconditions for this call.
    62            unsafe { Ok(Layout { size, align: mem::transmute(align) }) }
    63        } else {
    64            Err(LayoutError)
    65        }
    66    }
    67
    68    #[inline]
    69    const fn is_size_align_valid(size: usize, align: usize) -> bool {
    70        let Some(align) = Alignment::new(align) else { return false };
    71        if size > Self::max_size_for_align(align) {
    72            return false;
    73        }
    74        true
    75    }
    76
    77    #[inline(always)]
    78    const fn max_size_for_align(align: Alignment) -> usize {
    79        // (power-of-two implies align != 0.)
    80
    81        // Rounded up size is:
    82        //   size_rounded_up = (size + align - 1) & !(align - 1);
    83        //
    84        // We know from above that align != 0. If adding (align - 1)
    85        // does not overflow, then rounding up will be fine.
    86        //
    87        // Conversely, &-masking with !(align - 1) will subtract off
    88        // only low-order-bits. Thus if overflow occurs with the sum,
    89        // the &-mask cannot subtract enough to undo that overflow.
    90        //
    91        // Above implies that checking for summation overflow is both
    92        // necessary and sufficient.
    93
    94        // SAFETY: the maximum possible alignment is `isize::MAX + 1`,
    95        // so the subtraction cannot overflow.
    96        unsafe { unchecked_sub(isize::MAX as usize + 1, align.as_usize()) }
    97    }
    98
    99    /// Internal helper constructor to skip revalidating alignment validity.
    100    #[inline]
    101    const fn from_size_alignment(size: usize, align: Alignment) -> Result<Self, LayoutError> {
    102        if size > Self::max_size_for_align(align) {
    103            return Err(LayoutError);
    104        }
    105
    106        // SAFETY: Layout::size invariants checked above.
    107        Ok(Layout { size, align })
    108    }
    109
    110    /// Creates a layout, bypassing all checks.
    111    ///
    112    /// # Safety
    113    ///
    114    /// This function is unsafe as it does not verify the preconditions from
    115    /// [`Layout::from_size_align`].
    116    #[stable(feature = "alloc_layout", since = "1.28.0")]
    117    #[rustc_const_stable(feature = "const_alloc_layout_unchecked", since = "1.36.0")]
    118    #[must_use]
    119    #[inline]
    120    #[track_caller]
    121    pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
    122        assert_unsafe_precondition!(
    123            check_library_ub,
    124            "Layout::from_size_align_unchecked requires that align is a power of 2 \
    125            and the rounded-up allocation size does not exceed isize::MAX",
    126            (
    127                size: usize = size,
    128                align: usize = align,
    129            ) => Layout::is_size_align_valid(size, align)
    130        );
    131        // SAFETY: the caller is required to uphold the preconditions.
    132        unsafe { Layout { size, align: mem::transmute(align) } }
    133    }
    134
    135    /// The minimum size in bytes for a memory block of this layout.
    136    #[stable(feature = "alloc_layout", since = "1.28.0")]
    137    #[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
    138    #[must_use]
    139    #[inline]
    140    pub const fn size(&self) -> usize {
    141        self.size
    142    }
    143
    144    /// The minimum byte alignment for a memory block of this layout.
    145    ///
    146    /// The returned alignment is guaranteed to be a power of two.
    147    #[stable(feature = "alloc_layout", since = "1.28.0")]
    148    #[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
    149    #[must_use = "this returns the minimum alignment, \
    150                  without modifying the layout"]
    151    #[inline]
    152    pub const fn align(&self) -> usize {
    153        self.align.as_usize()
    154    }
    155
    156    /// Constructs a `Layout` suitable for holding a value of type `T`.
    157    #[stable(feature = "alloc_layout", since = "1.28.0")]
    158    #[rustc_const_stable(feature = "alloc_layout_const_new", since = "1.42.0")]
    159    #[must_use]
    160    #[inline]
    161    pub const fn new<T>() -> Self {
    162        <T as SizedTypeProperties>::LAYOUT
    163    }
    164
    165    /// Produces layout describing a record that could be used to
    166    /// allocate backing structure for `T` (which could be a trait
    167    /// or other unsized type like a slice).
    168    #[stable(feature = "alloc_layout", since = "1.28.0")]
    169    #[rustc_const_stable(feature = "const_alloc_layout", since = "1.85.0")]
    170    #[must_use]
    171    #[inline]
    172    pub const fn for_value<T: ?Sized>(t: &T) -> Self {
    173        let (size, align) = (size_of_val(t), align_of_val(t));
    174        // SAFETY: see rationale in `new` for why this is using the unsafe variant
    175        unsafe { Layout::from_size_align_unchecked(size, align) }
    176    }
    177
    178    /// Produces layout describing a record that could be used to
    179    /// allocate backing structure for `T` (which could be a trait
    180    /// or other unsized type like a slice).
    181    ///
    182    /// # Safety
    183    ///
    184    /// This function is only safe to call if the following conditions hold:
    185    ///
    186    /// - If `T` is `Sized`, this function is always safe to call.
    187    /// - If the unsized tail of `T` is:
    188    ///     - a [slice], then the length of the slice tail must be an initialized
    189    ///       integer, and the size of the *entire value*
    190    ///       (dynamic tail length + statically sized prefix) must fit in `isize`.
    191    ///       For the special case where the dynamic tail length is 0, this function
    192    ///       is safe to call.
    193    ///     - a [trait object], then the vtable part of the pointer must point
    194    ///       to a valid vtable for the type `T` acquired by an unsizing coercion,
    195    ///       and the size of the *entire value*
    196    ///       (dynamic tail length + statically sized prefix) must fit in `isize`.
    197    ///     - an (unstable) [extern type], then this function is always safe to
    198    ///       call, but may panic or otherwise return the wrong value, as the
    199    ///       extern type's layout is not known. This is the same behavior as
    200    ///       [`Layout::for_value`] on a reference to an extern type tail.
    201    ///     - otherwise, it is conservatively not allowed to call this function.
    202    ///
    203    /// [trait object]: ../../book/ch17-02-trait-objects.html
    204    /// [extern type]: ../../unstable-book/language-features/extern-types.html
    205    #[unstable(feature = "layout_for_ptr", issue = "69835")]
    206    #[must_use]
    207    pub const unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Self {
    208        // SAFETY: we pass along the prerequisites of these functions to the caller
    209        let (size, align) = unsafe { (mem::size_of_val_raw(t), mem::align_of_val_raw(t)) };
    210        // SAFETY: see rationale in `new` for why this is using the unsafe variant
    211        unsafe { Layout::from_size_align_unchecked(size, align) }
    212    }
    213
    214    /// Creates a `NonNull` that is dangling, but well-aligned for this Layout.
    215    ///
    216    /// Note that the address of the returned pointer may potentially
    217    /// be that of a valid pointer, which means this must not be used
    218    /// as a "not yet initialized" sentinel value.
    219    /// Types that lazily allocate must track initialization by some other means.
    220    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
    221    #[must_use]
    222    #[inline]
    223    pub const fn dangling(&self) -> NonNull<u8> {
    224        NonNull::without_provenance(self.align.as_nonzero())
    225    }
    226
    227    /// Creates a layout describing the record that can hold a value
    228    /// of the same layout as `self`, but that also is aligned to
    229    /// alignment `align` (measured in bytes).
    230    ///
    231    /// If `self` already meets the prescribed alignment, then returns
    232    /// `self`.
    233    ///
    234    /// Note that this method does not add any padding to the overall
    235    /// size, regardless of whether the returned layout has a different
    236    /// alignment. In other words, if `K` has size 16, `K.align_to(32)`
    237    /// will *still* have size 16.
    238    ///
    239    /// Returns an error if the combination of `self.size()` and the given
    240    /// `align` violates the conditions listed in [`Layout::from_size_align`].
    241    #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
    242    #[rustc_const_stable(feature = "const_alloc_layout", since = "1.85.0")]
    243    #[inline]
    244    pub const fn align_to(&self, align: usize) -> Result<Self, LayoutError> {
    245        if let Some(align) = Alignment::new(align) {
    246            Layout::from_size_alignment(self.size, Alignment::max(self.align, align))
    247        } else {
    248            Err(LayoutError)
    249        }
    250    }
    251
    252    /// Returns the amount of padding we must insert after `self`
    253    /// to ensure that the following address will satisfy `align`
    254    /// (measured in bytes).
    255    ///
    256    /// e.g., if `self.size()` is 9, then `self.padding_needed_for(4)`
    257    /// returns 3, because that is the minimum number of bytes of
    258    /// padding required to get a 4-aligned address (assuming that the
    259    /// corresponding memory block starts at a 4-aligned address).
    260    ///
    261    /// The return value of this function has no meaning if `align` is
    262    /// not a power-of-two.
    263    ///
    264    /// Note that the utility of the returned value requires `align`
    265    /// to be less than or equal to the alignment of the starting
    266    /// address for the whole allocated block of memory. One way to
    267    /// satisfy this constraint is to ensure `align <= self.align()`.
    268    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
    269    #[must_use = "this returns the padding needed, \
    270                  without modifying the `Layout`"]
    271    #[inline]
    272    pub const fn padding_needed_for(&self, align: usize) -> usize {
    273        // FIXME: Can we just change the type on this to `Alignment`?
    274        let Some(align) = Alignment::new(align) else { return usize::MAX };
    275        let len_rounded_up = self.size_rounded_up_to_custom_align(align);
    276        // SAFETY: Cannot overflow because the rounded-up value is never less
    277        unsafe { unchecked_sub(len_rounded_up, self.size) }
    278    }
    279
    280    /// Returns the smallest multiple of `align` greater than or equal to `self.size()`.
    281    ///
    282    /// This can return at most `Alignment::MAX` (aka `isize::MAX + 1`)
    283    /// because the original size is at most `isize::MAX`.
    284    #[inline]
    285    const fn size_rounded_up_to_custom_align(&self, align: Alignment) -> usize {
    286        // SAFETY:
    287        // Rounded up value is:
    288        //   size_rounded_up = (size + align - 1) & !(align - 1);
    289        //
    290        // The arithmetic we do here can never overflow:
    291        //
    292        // 1. align is guaranteed to be > 0, so align - 1 is always
    293        //    valid.
    294        //
    295        // 2. size is at most `isize::MAX`, so adding `align - 1` (which is at
    296        //    most `isize::MAX`) can never overflow a `usize`.
    297        //
    298        // 3. masking by the alignment can remove at most `align - 1`,
    299        //    which is what we just added, thus the value we return is never
    300        //    less than the original `size`.
    301        //
    302        // (Size 0 Align MAX is already aligned, so stays the same, but things like
    303        // Size 1 Align MAX or Size isize::MAX Align 2 round up to `isize::MAX + 1`.)
    304        unsafe {
    305            let align_m1 = unchecked_sub(align.as_usize(), 1);
    306            unchecked_add(self.size, align_m1) & !align_m1
    307        }
    308    }
    309
    310    /// Creates a layout by rounding the size of this layout up to a multiple
    311    /// of the layout's alignment.
    312    ///
    313    /// This is equivalent to adding the result of `padding_needed_for`
    314    /// to the layout's current size.
    315    #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
    316    #[rustc_const_stable(feature = "const_alloc_layout", since = "1.85.0")]
    317    #[must_use = "this returns a new `Layout`, \
    318                  without modifying the original"]
    319    #[inline]
    320    pub const fn pad_to_align(&self) -> Layout {
    321        // This cannot overflow. Quoting from the invariant of Layout:
    322        // > `size`, when rounded up to the nearest multiple of `align`,
    323        // > must not overflow isize (i.e., the rounded value must be
    324        // > less than or equal to `isize::MAX`)
    325        let new_size = self.size_rounded_up_to_custom_align(self.align);
    326
    327        // SAFETY: padded size is guaranteed to not exceed `isize::MAX`.
    328        unsafe { Layout::from_size_align_unchecked(new_size, self.align()) }
    329    }
    330
    331    /// Creates a layout describing the record for `n` instances of
    332    /// `self`, with a suitable amount of padding between each to
    333    /// ensure that each instance is given its requested size and
    334    /// alignment. On success, returns `(k, offs)` where `k` is the
    335    /// layout of the array and `offs` is the distance between the start
    336    /// of each element in the array.
    337    ///
    338    /// (That distance between elements is sometimes known as "stride".)
    339    ///
    340    /// On arithmetic overflow, returns `LayoutError`.
    341    ///
    342    /// # Examples
    343    ///
    344    /// ```
    345    /// #![feature(alloc_layout_extra)]
    346    /// use std::alloc::Layout;
    347    ///
    348    /// // All rust types have a size that's a multiple of their alignment.
    349    /// let normal = Layout::from_size_align(12, 4).unwrap();
    350    /// let repeated = normal.repeat(3).unwrap();
    351    /// assert_eq!(repeated, (Layout::from_size_align(36, 4).unwrap(), 12));
    352    ///
    353    /// // But you can manually make layouts which don't meet that rule.
    354    /// let padding_needed = Layout::from_size_align(6, 4).unwrap();
    355    /// let repeated = padding_needed.repeat(3).unwrap();
    356    /// assert_eq!(repeated, (Layout::from_size_align(24, 4).unwrap(), 8));
    357    /// ```
    358    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
    359    #[inline]
    360    pub const fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutError> {
    361        let padded = self.pad_to_align();
    362        if let Ok(repeated) = padded.repeat_packed(n) {
    363            Ok((repeated, padded.size()))
    364        } else {
    365            Err(LayoutError)
    366        }
    367    }
    368
    369    /// Creates a layout describing the record for `self` followed by
    370    /// `next`, including any necessary padding to ensure that `next`
    371    /// will be properly aligned, but *no trailing padding*.
    372    ///
    373    /// In order to match C representation layout `repr(C)`, you should
    374    /// call `pad_to_align` after extending the layout with all fields.
    375    /// (There is no way to match the default Rust representation
    376    /// layout `repr(Rust)`, as it is unspecified.)
    377    ///
    378    /// Note that the alignment of the resulting layout will be the maximum of
    379    /// those of `self` and `next`, in order to ensure alignment of both parts.
    380    ///
    381    /// Returns `Ok((k, offset))`, where `k` is layout of the concatenated
    382    /// record and `offset` is the relative location, in bytes, of the
    383    /// start of the `next` embedded within the concatenated record
    384    /// (assuming that the record itself starts at offset 0).
    385    ///
    386    /// On arithmetic overflow, returns `LayoutError`.
    387    ///
    388    /// # Examples
    389    ///
    390    /// To calculate the layout of a `#[repr(C)]` structure and the offsets of
    391    /// the fields from its fields' layouts:
    392    ///
    393    /// ```rust
    394    /// # use std::alloc::{Layout, LayoutError};
    395    /// pub fn repr_c(fields: &[Layout]) -> Result<(Layout, Vec<usize>), LayoutError> {
    396    ///     let mut offsets = Vec::new();
    397    ///     let mut layout = Layout::from_size_align(0, 1)?;
    398    ///     for &field in fields {
    399    ///         let (new_layout, offset) = layout.extend(field)?;
    400    ///         layout = new_layout;
    401    ///         offsets.push(offset);
    402    ///     }
    403    ///     // Remember to finalize with `pad_to_align`!
    404    ///     Ok((layout.pad_to_align(), offsets))
    405    /// }
    406    /// # // test that it works
    407    /// # #[repr(C)] struct S { a: u64, b: u32, c: u16, d: u32 }
    408    /// # let s = Layout::new::<S>();
    409    /// # let u16 = Layout::new::<u16>();
    410    /// # let u32 = Layout::new::<u32>();
    411    /// # let u64 = Layout::new::<u64>();
    412    /// # assert_eq!(repr_c(&[u64, u32, u16, u32]), Ok((s, vec![0, 8, 12, 16])));
    413    /// ```
    414    #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
    415    #[rustc_const_stable(feature = "const_alloc_layout", since = "1.85.0")]
    416    #[inline]
    417    pub const fn extend(&self, next: Self) -> Result<(Self, usize), LayoutError> {
    418        let new_align = Alignment::max(self.align, next.align);
    419        let offset = self.size_rounded_up_to_custom_align(next.align);
    420
    421        // SAFETY: `offset` is at most `isize::MAX + 1` (such as from aligning
    422        // to `Alignment::MAX`) and `next.size` is at most `isize::MAX` (from the
    423        // `Layout` type invariant).  Thus the largest possible `new_size` is
    424        // `isize::MAX + 1 + isize::MAX`, which is `usize::MAX`, and cannot overflow.
    425        let new_size = unsafe { unchecked_add(offset, next.size) };
    426
    427        if let Ok(layout) = Layout::from_size_alignment(new_size, new_align) {
    428            Ok((layout, offset))
    429        } else {
    430            Err(LayoutError)
    431        }
    432    }
    433
    434    /// Creates a layout describing the record for `n` instances of
    435    /// `self`, with no padding between each instance.
    436    ///
    437    /// Note that, unlike `repeat`, `repeat_packed` does not guarantee
    438    /// that the repeated instances of `self` will be properly
    439    /// aligned, even if a given instance of `self` is properly
    440    /// aligned. In other words, if the layout returned by
    441    /// `repeat_packed` is used to allocate an array, it is not
    442    /// guaranteed that all elements in the array will be properly
    443    /// aligned.
    444    ///
    445    /// On arithmetic overflow, returns `LayoutError`.
    446    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
    447    #[inline]
    448    pub const fn repeat_packed(&self, n: usize) -> Result<Self, LayoutError> {
    449        if let Some(size) = self.size.checked_mul(n) {
    450            // The safe constructor is called here to enforce the isize size limit.
    451            Layout::from_size_alignment(size, self.align)
    452        } else {
    453            Err(LayoutError)
    454        }
    455    }
    456
    457    /// Creates a layout describing the record for `self` followed by
    458    /// `next` with no additional padding between the two. Since no
    459    /// padding is inserted, the alignment of `next` is irrelevant,
    460    /// and is not incorporated *at all* into the resulting layout.
    461    ///
    462    /// On arithmetic overflow, returns `LayoutError`.
    463    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
    464    #[inline]
    465    pub const fn extend_packed(&self, next: Self) -> Result<Self, LayoutError> {
    466        // SAFETY: each `size` is at most `isize::MAX == usize::MAX/2`, so the
    467        // sum is at most `usize::MAX/2*2 == usize::MAX - 1`, and cannot overflow.
    468        let new_size = unsafe { unchecked_add(self.size, next.size) };
    469        // The safe constructor enforces that the new size isn't too big for the alignment
    470        Layout::from_size_alignment(new_size, self.align)
    471    }
    472
    473    /// Creates a layout describing the record for a `[T; n]`.
    474    ///
    475    /// On arithmetic overflow or when the total size would exceed
    476    /// `isize::MAX`, returns `LayoutError`.
    477    #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
    478    #[rustc_const_stable(feature = "const_alloc_layout", since = "1.85.0")]
    479    #[inline]
    480    pub const fn array<T>(n: usize) -> Result<Self, LayoutError> {
    481        // Reduce the amount of code we need to monomorphize per `T`.
    482        return inner(T::LAYOUT, n);
    483
    484        #[inline]
    485        const fn inner(element_layout: Layout, n: usize) -> Result<Layout, LayoutError> {
    486            let Layout { size: element_size, align } = element_layout;
    487
    488            // We need to check two things about the size:
    489            //  - That the total size won't overflow a `usize`, and
    490            //  - That the total size still fits in an `isize`.
    491            // By using division we can check them both with a single threshold.
    492            // That'd usually be a bad idea, but thankfully here the element size
    493            // and alignment are constants, so the compiler will fold all of it.
    494            if element_size != 0 && n > Layout::max_size_for_align(align) / element_size {
    495                return Err(LayoutError);
    496            }
    497
    498            // SAFETY: We just checked that we won't overflow `usize` when we multiply.
    499            // This is a useless hint inside this function, but after inlining this helps
    500            // deduplicate checks for whether the overall capacity is zero (e.g., in RawVec's
    501            // allocation path) before/after this multiplication.
    502            let array_size = unsafe { unchecked_mul(element_size, n) };
    503
    504            // SAFETY: We just checked above that the `array_size` will not
    505            // exceed `isize::MAX` even when rounded up to the alignment.
    506            // And `Alignment` guarantees it's a power of two.
    507            unsafe { Ok(Layout::from_size_align_unchecked(array_size, align.as_usize())) }
    508        }
    509    }
    510
    511    /// Perma-unstable access to `align` as `Alignment` type.
    512    #[unstable(issue = "none", feature = "std_internals")]
    513    #[doc(hidden)]
    514    #[inline]
    515    pub const fn alignment(&self) -> Alignment {
    516        self.align
    517    }
    518}
    519
    520#[stable(feature = "alloc_layout", since = "1.28.0")]
    521#[deprecated(
    522    since = "1.52.0",
    523    note = "Name does not follow std convention, use LayoutError",
    524    suggestion = "LayoutError"
    525)]
    526pub type LayoutErr = LayoutError;
    527
    528/// The `LayoutError` is returned when the parameters given
    529/// to `Layout::from_size_align`
    530/// or some other `Layout` constructor
    531/// do not satisfy its documented constraints.
    532#[stable(feature = "alloc_layout_error", since = "1.50.0")]
    533#[non_exhaustive]
    534#[derive(Clone, PartialEq, Eq, Debug)]
    535pub struct LayoutError;
    536
    537#[stable(feature = "alloc_layout", since = "1.28.0")]
    538impl Error for LayoutError {}
    539
    540// (we need this for downstream impl of trait Error)
    541#[stable(feature = "alloc_layout", since = "1.28.0")]
    542impl fmt::Display for LayoutError {
    543    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    544        f.write_str("invalid parameters to Layout::from_size_align")
    545    }
    546}