Skip to main content

rustc_abi/
lib.rs

1// tidy-alphabetical-start
2#![cfg_attr(bootstrap, feature(assert_matches))]
3#![cfg_attr(feature = "nightly", allow(internal_features))]
4#![cfg_attr(feature = "nightly", feature(rustc_attrs))]
5#![cfg_attr(feature = "nightly", feature(step_trait))]
6// tidy-alphabetical-end
7
8/*! ABI handling for rustc
9
10## What is an "ABI"?
11
12Literally, "application binary interface", which means it is everything about how code interacts,
13at the machine level, with other code. This means it technically covers all of the following:
14- object binary format for e.g. relocations or offset tables
15- in-memory layout of types
16- procedure calling conventions
17
18When we discuss "ABI" in the context of rustc, we are probably discussing calling conventions.
19To describe those `rustc_abi` also covers type layout, as it must for values passed on the stack.
20Despite `rustc_abi` being about calling conventions, it is good to remember these usages exist.
21You will encounter all of them and more if you study target-specific codegen enough!
22Even in general conversation, when someone says "the Rust ABI is unstable", it may allude to
23either or both of
24- `repr(Rust)` types have a mostly-unspecified layout
25- `extern "Rust" fn(A) -> R` has an unspecified calling convention
26
27## Crate Goal
28
29ABI is a foundational concept, so the `rustc_abi` crate serves as an equally foundational crate.
30It cannot carry all details relevant to an ABI: those permeate code generation and linkage.
31Instead, `rustc_abi` is intended to provide the interface for reasoning about the binary interface.
32It should contain traits and types that other crates then use in their implementation.
33For example, a platform's `extern "C" fn` calling convention will be implemented in `rustc_target`
34but `rustc_abi` contains the types for calculating layout and describing register-passing.
35This makes it easier to describe things in the same way across targets, codegen backends, and
36even other Rust compilers, such as rust-analyzer!
37
38*/
39
40use std::fmt;
41#[cfg(feature = "nightly")]
42use std::iter::Step;
43use std::num::{NonZeroUsize, ParseIntError};
44use std::ops::{Add, AddAssign, Deref, Mul, RangeFull, RangeInclusive, Sub};
45use std::str::FromStr;
46
47use bitflags::bitflags;
48#[cfg(feature = "nightly")]
49use rustc_data_structures::stable_hasher::StableOrd;
50#[cfg(feature = "nightly")]
51use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, msg};
52use rustc_hashes::Hash64;
53use rustc_index::{Idx, IndexSlice, IndexVec};
54#[cfg(feature = "nightly")]
55use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_Generic};
56
57mod callconv;
58mod canon_abi;
59mod extern_abi;
60mod layout;
61#[cfg(test)]
62mod tests;
63
64pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind};
65pub use canon_abi::{ArmCall, CanonAbi, InterruptKind, X86Call};
66#[cfg(feature = "nightly")]
67pub use extern_abi::CVariadicStatus;
68pub use extern_abi::{ExternAbi, all_names};
69pub use layout::{FIRST_VARIANT, FieldIdx, LayoutCalculator, LayoutCalculatorError, VariantIdx};
70#[cfg(feature = "nightly")]
71pub use layout::{Layout, TyAbiInterface, TyAndLayout};
72
73#[derive(#[automatically_derived]
impl ::core::clone::Clone for ReprFlags {
    #[inline]
    fn clone(&self) -> ReprFlags {
        let _: ::core::clone::AssertParamIsClone<u8>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for ReprFlags { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for ReprFlags {
    #[inline]
    fn eq(&self, other: &ReprFlags) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ReprFlags {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<u8>;
    }
}Eq, #[automatically_derived]
impl ::core::default::Default for ReprFlags {
    #[inline]
    fn default() -> ReprFlags {
        ReprFlags(::core::default::Default::default())
    }
}Default)]
74#[cfg_attr(
75    feature = "nightly",
76    derive(const _: () =
    {
        impl<__E: ::rustc_serialize::Encoder>
            ::rustc_serialize::Encodable<__E> for ReprFlags {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    ReprFlags(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable_NoContext, const _: () =
    {
        impl<__D: ::rustc_serialize::Decoder>
            ::rustc_serialize::Decodable<__D> for ReprFlags {
            fn decode(__decoder: &mut __D) -> Self {
                ReprFlags(::rustc_serialize::Decodable::decode(__decoder))
            }
        }
    };Decodable_NoContext, const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for ReprFlags where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    ReprFlags(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic)
77)]
78pub struct ReprFlags(u8);
79
80impl ReprFlags {
    #[allow(deprecated, non_upper_case_globals,)]
    pub const IS_C: Self = Self::from_bits_retain(1 << 0);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const IS_SIMD: Self = Self::from_bits_retain(1 << 1);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const IS_TRANSPARENT: Self = Self::from_bits_retain(1 << 2);
    #[doc = r" Internal only for now. If true, don't reorder fields."]
    #[doc = r" On its own it does not prevent ABI optimizations."]
    #[allow(deprecated, non_upper_case_globals,)]
    pub const IS_LINEAR: Self = Self::from_bits_retain(1 << 3);
    #[doc =
    r" If true, the type's crate has opted into layout randomization."]
    #[doc =
    r" Other flags can still inhibit reordering and thus randomization."]
    #[doc = r" The seed stored in `ReprOptions.field_shuffle_seed`."]
    #[allow(deprecated, non_upper_case_globals,)]
    pub const RANDOMIZE_LAYOUT: Self = Self::from_bits_retain(1 << 4);
    #[doc =
    r" If true, the type is always passed indirectly by non-Rustic ABIs."]
    #[doc =
    r" See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details."]
    #[allow(deprecated, non_upper_case_globals,)]
    pub const PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS: Self =
        Self::from_bits_retain(1 << 5);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const IS_SCALABLE: Self = Self::from_bits_retain(1 << 6);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const FIELD_ORDER_UNOPTIMIZABLE: Self =
        Self::from_bits_retain(ReprFlags::IS_C.bits() |
                        ReprFlags::IS_SIMD.bits() | ReprFlags::IS_SCALABLE.bits() |
                ReprFlags::IS_LINEAR.bits());
    #[allow(deprecated, non_upper_case_globals,)]
    pub const ABI_UNOPTIMIZABLE: Self =
        Self::from_bits_retain(ReprFlags::IS_C.bits() |
                ReprFlags::IS_SIMD.bits());
}
impl ::bitflags::Flags for ReprFlags {
    const FLAGS: &'static [::bitflags::Flag<ReprFlags>] =
        &[{

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("IS_C", ReprFlags::IS_C)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("IS_SIMD", ReprFlags::IS_SIMD)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("IS_TRANSPARENT",
                            ReprFlags::IS_TRANSPARENT)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("IS_LINEAR", ReprFlags::IS_LINEAR)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("RANDOMIZE_LAYOUT",
                            ReprFlags::RANDOMIZE_LAYOUT)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS",
                            ReprFlags::PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("IS_SCALABLE", ReprFlags::IS_SCALABLE)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("FIELD_ORDER_UNOPTIMIZABLE",
                            ReprFlags::FIELD_ORDER_UNOPTIMIZABLE)
                    },
                    {

                        #[allow(deprecated, non_upper_case_globals,)]
                        ::bitflags::Flag::new("ABI_UNOPTIMIZABLE",
                            ReprFlags::ABI_UNOPTIMIZABLE)
                    }];
    type Bits = u8;
    fn bits(&self) -> u8 { ReprFlags::bits(self) }
    fn from_bits_retain(bits: u8) -> ReprFlags {
        ReprFlags::from_bits_retain(bits)
    }
}
#[allow(dead_code, deprecated, unused_doc_comments, unused_attributes,
unused_mut, unused_imports, non_upper_case_globals, clippy ::
assign_op_pattern, clippy :: iter_without_into_iter,)]
const _: () =
    {
        #[allow(dead_code, deprecated, unused_attributes)]
        impl ReprFlags {
            /// Get a flags value with all bits unset.
            #[inline]
            pub const fn empty() -> Self {
                Self(<u8 as ::bitflags::Bits>::EMPTY)
            }
            /// Get a flags value with all known bits set.
            #[inline]
            pub const fn all() -> Self {
                let mut truncated = <u8 as ::bitflags::Bits>::EMPTY;
                let mut i = 0;
                {
                    {
                        let flag =
                            <ReprFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ReprFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ReprFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ReprFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ReprFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ReprFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ReprFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ReprFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                {
                    {
                        let flag =
                            <ReprFlags as ::bitflags::Flags>::FLAGS[i].value().bits();
                        truncated = truncated | flag;
                        i += 1;
                    }
                };
                let _ = i;
                Self(truncated)
            }
            /// Get the underlying bits value.
            ///
            /// The returned value is exactly the bits set in this flags value.
            #[inline]
            pub const fn bits(&self) -> u8 { self.0 }
            /// Convert from a bits value.
            ///
            /// This method will return `None` if any unknown bits are set.
            #[inline]
            pub const fn from_bits(bits: u8)
                -> ::bitflags::__private::core::option::Option<Self> {
                let truncated = Self::from_bits_truncate(bits).0;
                if truncated == bits {
                    ::bitflags::__private::core::option::Option::Some(Self(bits))
                } else { ::bitflags::__private::core::option::Option::None }
            }
            /// Convert from a bits value, unsetting any unknown bits.
            #[inline]
            pub const fn from_bits_truncate(bits: u8) -> Self {
                Self(bits & Self::all().0)
            }
            /// Convert from a bits value exactly.
            #[inline]
            pub const fn from_bits_retain(bits: u8) -> Self { Self(bits) }
            /// Get a flags value with the bits of a flag with the given name set.
            ///
            /// This method will return `None` if `name` is empty or doesn't
            /// correspond to any named flag.
            #[inline]
            pub fn from_name(name: &str)
                -> ::bitflags::__private::core::option::Option<Self> {
                {
                    if name == "IS_C" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ReprFlags::IS_C.bits()));
                    }
                };
                ;
                {
                    if name == "IS_SIMD" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ReprFlags::IS_SIMD.bits()));
                    }
                };
                ;
                {
                    if name == "IS_TRANSPARENT" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ReprFlags::IS_TRANSPARENT.bits()));
                    }
                };
                ;
                {
                    if name == "IS_LINEAR" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ReprFlags::IS_LINEAR.bits()));
                    }
                };
                ;
                {
                    if name == "RANDOMIZE_LAYOUT" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ReprFlags::RANDOMIZE_LAYOUT.bits()));
                    }
                };
                ;
                {
                    if name == "PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ReprFlags::PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS.bits()));
                    }
                };
                ;
                {
                    if name == "IS_SCALABLE" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ReprFlags::IS_SCALABLE.bits()));
                    }
                };
                ;
                {
                    if name == "FIELD_ORDER_UNOPTIMIZABLE" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ReprFlags::FIELD_ORDER_UNOPTIMIZABLE.bits()));
                    }
                };
                ;
                {
                    if name == "ABI_UNOPTIMIZABLE" {
                        return ::bitflags::__private::core::option::Option::Some(Self(ReprFlags::ABI_UNOPTIMIZABLE.bits()));
                    }
                };
                ;
                let _ = name;
                ::bitflags::__private::core::option::Option::None
            }
            /// Whether all bits in this flags value are unset.
            #[inline]
            pub const fn is_empty(&self) -> bool {
                self.0 == <u8 as ::bitflags::Bits>::EMPTY
            }
            /// Whether all known bits in this flags value are set.
            #[inline]
            pub const fn is_all(&self) -> bool {
                Self::all().0 | self.0 == self.0
            }
            /// Whether any set bits in a source flags value are also set in a target flags value.
            #[inline]
            pub const fn intersects(&self, other: Self) -> bool {
                self.0 & other.0 != <u8 as ::bitflags::Bits>::EMPTY
            }
            /// Whether all set bits in a source flags value are also set in a target flags value.
            #[inline]
            pub const fn contains(&self, other: Self) -> bool {
                self.0 & other.0 == other.0
            }
            /// The bitwise or (`|`) of the bits in two flags values.
            #[inline]
            pub fn insert(&mut self, other: Self) {
                *self = Self(self.0).union(other);
            }
            /// The intersection of a source flags value with the complement of a target flags
            /// value (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `remove` won't truncate `other`, but the `!` operator will.
            #[inline]
            pub fn remove(&mut self, other: Self) {
                *self = Self(self.0).difference(other);
            }
            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
            #[inline]
            pub fn toggle(&mut self, other: Self) {
                *self = Self(self.0).symmetric_difference(other);
            }
            /// Call `insert` when `value` is `true` or `remove` when `value` is `false`.
            #[inline]
            pub fn set(&mut self, other: Self, value: bool) {
                if value { self.insert(other); } else { self.remove(other); }
            }
            /// The bitwise and (`&`) of the bits in two flags values.
            #[inline]
            #[must_use]
            pub const fn intersection(self, other: Self) -> Self {
                Self(self.0 & other.0)
            }
            /// The bitwise or (`|`) of the bits in two flags values.
            #[inline]
            #[must_use]
            pub const fn union(self, other: Self) -> Self {
                Self(self.0 | other.0)
            }
            /// The intersection of a source flags value with the complement of a target flags
            /// value (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            #[must_use]
            pub const fn difference(self, other: Self) -> Self {
                Self(self.0 & !other.0)
            }
            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
            #[inline]
            #[must_use]
            pub const fn symmetric_difference(self, other: Self) -> Self {
                Self(self.0 ^ other.0)
            }
            /// The bitwise negation (`!`) of the bits in a flags value, truncating the result.
            #[inline]
            #[must_use]
            pub const fn complement(self) -> Self {
                Self::from_bits_truncate(!self.0)
            }
        }
        impl ::bitflags::__private::core::fmt::Binary for ReprFlags {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::Binary::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::fmt::Octal for ReprFlags {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::Octal::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::fmt::LowerHex for ReprFlags {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::LowerHex::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::fmt::UpperHex for ReprFlags {
            fn fmt(&self, f: &mut ::bitflags::__private::core::fmt::Formatter)
                -> ::bitflags::__private::core::fmt::Result {
                let inner = self.0;
                ::bitflags::__private::core::fmt::UpperHex::fmt(&inner, f)
            }
        }
        impl ::bitflags::__private::core::ops::BitOr for ReprFlags {
            type Output = Self;
            /// The bitwise or (`|`) of the bits in two flags values.
            #[inline]
            fn bitor(self, other: ReprFlags) -> Self { self.union(other) }
        }
        impl ::bitflags::__private::core::ops::BitOrAssign for ReprFlags {
            /// The bitwise or (`|`) of the bits in two flags values.
            #[inline]
            fn bitor_assign(&mut self, other: Self) { self.insert(other); }
        }
        impl ::bitflags::__private::core::ops::BitXor for ReprFlags {
            type Output = Self;
            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
            #[inline]
            fn bitxor(self, other: Self) -> Self {
                self.symmetric_difference(other)
            }
        }
        impl ::bitflags::__private::core::ops::BitXorAssign for ReprFlags {
            /// The bitwise exclusive-or (`^`) of the bits in two flags values.
            #[inline]
            fn bitxor_assign(&mut self, other: Self) { self.toggle(other); }
        }
        impl ::bitflags::__private::core::ops::BitAnd for ReprFlags {
            type Output = Self;
            /// The bitwise and (`&`) of the bits in two flags values.
            #[inline]
            fn bitand(self, other: Self) -> Self { self.intersection(other) }
        }
        impl ::bitflags::__private::core::ops::BitAndAssign for ReprFlags {
            /// The bitwise and (`&`) of the bits in two flags values.
            #[inline]
            fn bitand_assign(&mut self, other: Self) {
                *self =
                    Self::from_bits_retain(self.bits()).intersection(other);
            }
        }
        impl ::bitflags::__private::core::ops::Sub for ReprFlags {
            type Output = Self;
            /// The intersection of a source flags value with the complement of a target flags value (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub(self, other: Self) -> Self { self.difference(other) }
        }
        impl ::bitflags::__private::core::ops::SubAssign for ReprFlags {
            /// The intersection of a source flags value with the complement of a target flags value (`&!`).
            ///
            /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
            /// `difference` won't truncate `other`, but the `!` operator will.
            #[inline]
            fn sub_assign(&mut self, other: Self) { self.remove(other); }
        }
        impl ::bitflags::__private::core::ops::Not for ReprFlags {
            type Output = Self;
            /// The bitwise negation (`!`) of the bits in a flags value, truncating the result.
            #[inline]
            fn not(self) -> Self { self.complement() }
        }
        impl ::bitflags::__private::core::iter::Extend<ReprFlags> for
            ReprFlags {
            /// The bitwise or (`|`) of the bits in each flags value.
            fn extend<T: ::bitflags::__private::core::iter::IntoIterator<Item
                = Self>>(&mut self, iterator: T) {
                for item in iterator { self.insert(item) }
            }
        }
        impl ::bitflags::__private::core::iter::FromIterator<ReprFlags> for
            ReprFlags {
            /// The bitwise or (`|`) of the bits in each flags value.
            fn from_iter<T: ::bitflags::__private::core::iter::IntoIterator<Item
                = Self>>(iterator: T) -> Self {
                use ::bitflags::__private::core::iter::Extend;
                let mut result = Self::empty();
                result.extend(iterator);
                result
            }
        }
        impl ReprFlags {
            /// Yield a set of contained flags values.
            ///
            /// Each yielded flags value will correspond to a defined named flag. Any unknown bits
            /// will be yielded together as a final flags value.
            #[inline]
            pub const fn iter(&self) -> ::bitflags::iter::Iter<ReprFlags> {
                ::bitflags::iter::Iter::__private_const_new(<ReprFlags as
                        ::bitflags::Flags>::FLAGS,
                    ReprFlags::from_bits_retain(self.bits()),
                    ReprFlags::from_bits_retain(self.bits()))
            }
            /// Yield a set of contained named flags values.
            ///
            /// This method is like [`iter`](#method.iter), except only yields bits in contained named flags.
            /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded.
            #[inline]
            pub const fn iter_names(&self)
                -> ::bitflags::iter::IterNames<ReprFlags> {
                ::bitflags::iter::IterNames::__private_const_new(<ReprFlags as
                        ::bitflags::Flags>::FLAGS,
                    ReprFlags::from_bits_retain(self.bits()),
                    ReprFlags::from_bits_retain(self.bits()))
            }
        }
        impl ::bitflags::__private::core::iter::IntoIterator for ReprFlags {
            type Item = ReprFlags;
            type IntoIter = ::bitflags::iter::Iter<ReprFlags>;
            fn into_iter(self) -> Self::IntoIter { self.iter() }
        }
    };bitflags! {
81    impl ReprFlags: u8 {
82        const IS_C               = 1 << 0;
83        const IS_SIMD            = 1 << 1;
84        const IS_TRANSPARENT     = 1 << 2;
85        /// Internal only for now. If true, don't reorder fields.
86        /// On its own it does not prevent ABI optimizations.
87        const IS_LINEAR          = 1 << 3;
88        /// If true, the type's crate has opted into layout randomization.
89        /// Other flags can still inhibit reordering and thus randomization.
90        /// The seed stored in `ReprOptions.field_shuffle_seed`.
91        const RANDOMIZE_LAYOUT   = 1 << 4;
92        /// If true, the type is always passed indirectly by non-Rustic ABIs.
93        /// See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details.
94        const PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS = 1 << 5;
95        const IS_SCALABLE        = 1 << 6;
96         // Any of these flags being set prevent field reordering optimisation.
97        const FIELD_ORDER_UNOPTIMIZABLE = ReprFlags::IS_C.bits()
98                                 | ReprFlags::IS_SIMD.bits()
99                                 | ReprFlags::IS_SCALABLE.bits()
100                                 | ReprFlags::IS_LINEAR.bits();
101        const ABI_UNOPTIMIZABLE = ReprFlags::IS_C.bits() | ReprFlags::IS_SIMD.bits();
102    }
103}
104
105// This is the same as `rustc_data_structures::external_bitflags_debug` but without the
106// `rustc_data_structures` to make it build on stable.
107impl std::fmt::Debug for ReprFlags {
108    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109        bitflags::parser::to_writer(self, f)
110    }
111}
112
113#[derive(#[automatically_derived]
impl ::core::marker::Copy for IntegerType { }Copy, #[automatically_derived]
impl ::core::clone::Clone for IntegerType {
    #[inline]
    fn clone(&self) -> IntegerType {
        let _: ::core::clone::AssertParamIsClone<bool>;
        let _: ::core::clone::AssertParamIsClone<Integer>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for IntegerType {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            IntegerType::Pointer(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Pointer", &__self_0),
            IntegerType::Fixed(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f, "Fixed",
                    __self_0, &__self_1),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::Eq for IntegerType {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<bool>;
        let _: ::core::cmp::AssertParamIsEq<Integer>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for IntegerType {
    #[inline]
    fn eq(&self, other: &IntegerType) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (IntegerType::Pointer(__self_0),
                    IntegerType::Pointer(__arg1_0)) => __self_0 == __arg1_0,
                (IntegerType::Fixed(__self_0, __self_1),
                    IntegerType::Fixed(__arg1_0, __arg1_1)) =>
                    __self_1 == __arg1_1 && __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq)]
114#[cfg_attr(
115    feature = "nightly",
116    derive(const _: () =
    {
        impl<__E: ::rustc_serialize::Encoder>
            ::rustc_serialize::Encodable<__E> for IntegerType {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        IntegerType::Pointer(ref __binding_0) => { 0usize }
                        IntegerType::Fixed(ref __binding_0, ref __binding_1) => {
                            1usize
                        }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    IntegerType::Pointer(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    IntegerType::Fixed(ref __binding_0, ref __binding_1) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                    }
                }
            }
        }
    };Encodable_NoContext, const _: () =
    {
        impl<__D: ::rustc_serialize::Decoder>
            ::rustc_serialize::Decodable<__D> for IntegerType {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        IntegerType::Pointer(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => {
                        IntegerType::Fixed(::rustc_serialize::Decodable::decode(__decoder),
                            ::rustc_serialize::Decodable::decode(__decoder))
                    }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `IntegerType`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable_NoContext, const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for IntegerType where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    IntegerType::Pointer(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    IntegerType::Fixed(ref __binding_0, ref __binding_1) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic)
117)]
118pub enum IntegerType {
119    /// Pointer-sized integer type, i.e. `isize` and `usize`. The field shows signedness, e.g.
120    /// `Pointer(true)` means `isize`.
121    Pointer(bool),
122    /// Fixed-sized integer type, e.g. `i8`, `u32`, `i128`. The bool field shows signedness, e.g.
123    /// `Fixed(I8, false)` means `u8`.
124    Fixed(Integer, bool),
125}
126
127impl IntegerType {
128    pub fn is_signed(&self) -> bool {
129        match self {
130            IntegerType::Pointer(b) => *b,
131            IntegerType::Fixed(_, b) => *b,
132        }
133    }
134}
135
136#[derive(#[automatically_derived]
impl ::core::marker::Copy for ScalableElt { }Copy, #[automatically_derived]
impl ::core::clone::Clone for ScalableElt {
    #[inline]
    fn clone(&self) -> ScalableElt {
        let _: ::core::clone::AssertParamIsClone<u16>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for ScalableElt {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            ScalableElt::ElementCount(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ElementCount", &__self_0),
            ScalableElt::Container =>
                ::core::fmt::Formatter::write_str(f, "Container"),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::Eq for ScalableElt {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<u16>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for ScalableElt {
    #[inline]
    fn eq(&self, other: &ScalableElt) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (ScalableElt::ElementCount(__self_0),
                    ScalableElt::ElementCount(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq)]
137#[cfg_attr(
138    feature = "nightly",
139    derive(const _: () =
    {
        impl<__E: ::rustc_serialize::Encoder>
            ::rustc_serialize::Encodable<__E> for ScalableElt {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        ScalableElt::ElementCount(ref __binding_0) => { 0usize }
                        ScalableElt::Container => { 1usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    ScalableElt::ElementCount(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    ScalableElt::Container => {}
                }
            }
        }
    };Encodable_NoContext, const _: () =
    {
        impl<__D: ::rustc_serialize::Decoder>
            ::rustc_serialize::Decodable<__D> for ScalableElt {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        ScalableElt::ElementCount(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => { ScalableElt::Container }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `ScalableElt`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable_NoContext, const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for ScalableElt where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    ScalableElt::ElementCount(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    ScalableElt::Container => {}
                }
            }
        }
    };HashStable_Generic)
140)]
141pub enum ScalableElt {
142    /// `N` in `rustc_scalable_vector(N)` - the element count of the scalable vector
143    ElementCount(u16),
144    /// `rustc_scalable_vector` w/out `N`, used for tuple types of scalable vectors that only
145    /// contain other scalable vectors
146    Container,
147}
148
149/// Represents the repr options provided by the user.
150#[derive(#[automatically_derived]
impl ::core::marker::Copy for ReprOptions { }Copy, #[automatically_derived]
impl ::core::clone::Clone for ReprOptions {
    #[inline]
    fn clone(&self) -> ReprOptions {
        let _: ::core::clone::AssertParamIsClone<Option<IntegerType>>;
        let _: ::core::clone::AssertParamIsClone<Option<Align>>;
        let _: ::core::clone::AssertParamIsClone<Option<Align>>;
        let _: ::core::clone::AssertParamIsClone<ReprFlags>;
        let _: ::core::clone::AssertParamIsClone<Option<ScalableElt>>;
        let _: ::core::clone::AssertParamIsClone<Hash64>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for ReprOptions {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            &["int", "align", "pack", "flags", "scalable",
                        "field_shuffle_seed"];
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.int, &self.align, &self.pack, &self.flags, &self.scalable,
                        &&self.field_shuffle_seed];
        ::core::fmt::Formatter::debug_struct_fields_finish(f, "ReprOptions",
            names, values)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::Eq for ReprOptions {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Option<IntegerType>>;
        let _: ::core::cmp::AssertParamIsEq<Option<Align>>;
        let _: ::core::cmp::AssertParamIsEq<Option<Align>>;
        let _: ::core::cmp::AssertParamIsEq<ReprFlags>;
        let _: ::core::cmp::AssertParamIsEq<Option<ScalableElt>>;
        let _: ::core::cmp::AssertParamIsEq<Hash64>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for ReprOptions {
    #[inline]
    fn eq(&self, other: &ReprOptions) -> bool {
        self.int == other.int && self.align == other.align &&
                        self.pack == other.pack && self.flags == other.flags &&
                self.scalable == other.scalable &&
            self.field_shuffle_seed == other.field_shuffle_seed
    }
}PartialEq, #[automatically_derived]
impl ::core::default::Default for ReprOptions {
    #[inline]
    fn default() -> ReprOptions {
        ReprOptions {
            int: ::core::default::Default::default(),
            align: ::core::default::Default::default(),
            pack: ::core::default::Default::default(),
            flags: ::core::default::Default::default(),
            scalable: ::core::default::Default::default(),
            field_shuffle_seed: ::core::default::Default::default(),
        }
    }
}Default)]
151#[cfg_attr(
152    feature = "nightly",
153    derive(const _: () =
    {
        impl<__E: ::rustc_serialize::Encoder>
            ::rustc_serialize::Encodable<__E> for ReprOptions {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    ReprOptions {
                        int: ref __binding_0,
                        align: ref __binding_1,
                        pack: ref __binding_2,
                        flags: ref __binding_3,
                        scalable: ref __binding_4,
                        field_shuffle_seed: ref __binding_5 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_2,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_3,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_4,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_5,
                            __encoder);
                    }
                }
            }
        }
    };Encodable_NoContext, const _: () =
    {
        impl<__D: ::rustc_serialize::Decoder>
            ::rustc_serialize::Decodable<__D> for ReprOptions {
            fn decode(__decoder: &mut __D) -> Self {
                ReprOptions {
                    int: ::rustc_serialize::Decodable::decode(__decoder),
                    align: ::rustc_serialize::Decodable::decode(__decoder),
                    pack: ::rustc_serialize::Decodable::decode(__decoder),
                    flags: ::rustc_serialize::Decodable::decode(__decoder),
                    scalable: ::rustc_serialize::Decodable::decode(__decoder),
                    field_shuffle_seed: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable_NoContext, const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for ReprOptions where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    ReprOptions {
                        int: ref __binding_0,
                        align: ref __binding_1,
                        pack: ref __binding_2,
                        flags: ref __binding_3,
                        scalable: ref __binding_4,
                        field_shuffle_seed: ref __binding_5 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                        { __binding_2.hash_stable(__hcx, __hasher); }
                        { __binding_3.hash_stable(__hcx, __hasher); }
                        { __binding_4.hash_stable(__hcx, __hasher); }
                        { __binding_5.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic)
154)]
155pub struct ReprOptions {
156    pub int: Option<IntegerType>,
157    pub align: Option<Align>,
158    pub pack: Option<Align>,
159    pub flags: ReprFlags,
160    /// `#[rustc_scalable_vector]`
161    pub scalable: Option<ScalableElt>,
162    /// The seed to be used for randomizing a type's layout
163    ///
164    /// Note: This could technically be a `u128` which would
165    /// be the "most accurate" hash as it'd encompass the item and crate
166    /// hash without loss, but it does pay the price of being larger.
167    /// Everything's a tradeoff, a 64-bit seed should be sufficient for our
168    /// purposes (primarily `-Z randomize-layout`)
169    pub field_shuffle_seed: Hash64,
170}
171
172impl ReprOptions {
173    #[inline]
174    pub fn simd(&self) -> bool {
175        self.flags.contains(ReprFlags::IS_SIMD)
176    }
177
178    #[inline]
179    pub fn scalable(&self) -> bool {
180        self.flags.contains(ReprFlags::IS_SCALABLE)
181    }
182
183    #[inline]
184    pub fn c(&self) -> bool {
185        self.flags.contains(ReprFlags::IS_C)
186    }
187
188    #[inline]
189    pub fn packed(&self) -> bool {
190        self.pack.is_some()
191    }
192
193    #[inline]
194    pub fn transparent(&self) -> bool {
195        self.flags.contains(ReprFlags::IS_TRANSPARENT)
196    }
197
198    #[inline]
199    pub fn linear(&self) -> bool {
200        self.flags.contains(ReprFlags::IS_LINEAR)
201    }
202
203    /// Returns the discriminant type, given these `repr` options.
204    /// This must only be called on enums!
205    ///
206    /// This is the "typeck type" of the discriminant, which is effectively the maximum size:
207    /// discriminant values will be wrapped to fit (with a lint). Layout can later decide to use a
208    /// smaller type for the tag that stores the discriminant at runtime and that will work just
209    /// fine, it just induces casts when getting/setting the discriminant.
210    pub fn discr_type(&self) -> IntegerType {
211        self.int.unwrap_or(IntegerType::Pointer(true))
212    }
213
214    /// Returns `true` if this `#[repr()]` should inhabit "smart enum
215    /// layout" optimizations, such as representing `Foo<&T>` as a
216    /// single pointer.
217    pub fn inhibit_enum_layout_opt(&self) -> bool {
218        self.c() || self.int.is_some()
219    }
220
221    pub fn inhibit_newtype_abi_optimization(&self) -> bool {
222        self.flags.intersects(ReprFlags::ABI_UNOPTIMIZABLE)
223    }
224
225    /// Returns `true` if this `#[repr()]` guarantees a fixed field order,
226    /// e.g. `repr(C)` or `repr(<int>)`.
227    pub fn inhibit_struct_field_reordering(&self) -> bool {
228        self.flags.intersects(ReprFlags::FIELD_ORDER_UNOPTIMIZABLE) || self.int.is_some()
229    }
230
231    /// Returns `true` if this type is valid for reordering and `-Z randomize-layout`
232    /// was enabled for its declaration crate.
233    pub fn can_randomize_type_layout(&self) -> bool {
234        !self.inhibit_struct_field_reordering() && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT)
235    }
236
237    /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations.
238    pub fn inhibits_union_abi_opt(&self) -> bool {
239        self.c()
240    }
241}
242
243/// The maximum supported number of lanes in a SIMD vector.
244///
245/// This value is selected based on backend support:
246/// * LLVM does not appear to have a vector width limit.
247/// * Cranelift stores the base-2 log of the lane count in a 4 bit integer.
248pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
249
250/// How pointers are represented in a given address space
251#[derive(#[automatically_derived]
impl ::core::marker::Copy for PointerSpec { }Copy, #[automatically_derived]
impl ::core::clone::Clone for PointerSpec {
    #[inline]
    fn clone(&self) -> PointerSpec {
        let _: ::core::clone::AssertParamIsClone<Size>;
        let _: ::core::clone::AssertParamIsClone<Align>;
        let _: ::core::clone::AssertParamIsClone<bool>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for PointerSpec {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field4_finish(f, "PointerSpec",
            "pointer_size", &self.pointer_size, "pointer_align",
            &self.pointer_align, "pointer_offset", &self.pointer_offset,
            "_is_fat", &&self._is_fat)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for PointerSpec {
    #[inline]
    fn eq(&self, other: &PointerSpec) -> bool {
        self._is_fat == other._is_fat &&
                    self.pointer_size == other.pointer_size &&
                self.pointer_align == other.pointer_align &&
            self.pointer_offset == other.pointer_offset
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for PointerSpec {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Size>;
        let _: ::core::cmp::AssertParamIsEq<Align>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq)]
252pub struct PointerSpec {
253    /// The size of the bitwise representation of the pointer.
254    pointer_size: Size,
255    /// The alignment of pointers for this address space
256    pointer_align: Align,
257    /// The size of the value a pointer can be offset by in this address space.
258    pointer_offset: Size,
259    /// Pointers into this address space contain extra metadata
260    /// FIXME(workingjubilee): Consider adequately reflecting this in the compiler?
261    _is_fat: bool,
262}
263
264/// Parsed [Data layout](https://llvm.org/docs/LangRef.html#data-layout)
265/// for a target, which contains everything needed to compute layouts.
266#[derive(#[automatically_derived]
impl ::core::fmt::Debug for TargetDataLayout {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            &["endian", "i1_align", "i8_align", "i16_align", "i32_align",
                        "i64_align", "i128_align", "f16_align", "f32_align",
                        "f64_align", "f128_align", "aggregate_align",
                        "vector_align", "default_address_space",
                        "default_address_space_pointer_spec", "address_space_info",
                        "instruction_address_space", "c_enum_min_size"];
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.endian, &self.i1_align, &self.i8_align, &self.i16_align,
                        &self.i32_align, &self.i64_align, &self.i128_align,
                        &self.f16_align, &self.f32_align, &self.f64_align,
                        &self.f128_align, &self.aggregate_align, &self.vector_align,
                        &self.default_address_space,
                        &self.default_address_space_pointer_spec,
                        &self.address_space_info, &self.instruction_address_space,
                        &&self.c_enum_min_size];
        ::core::fmt::Formatter::debug_struct_fields_finish(f,
            "TargetDataLayout", names, values)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for TargetDataLayout {
    #[inline]
    fn eq(&self, other: &TargetDataLayout) -> bool {
        self.endian == other.endian && self.i1_align == other.i1_align &&
                                                                        self.i8_align == other.i8_align &&
                                                                    self.i16_align == other.i16_align &&
                                                                self.i32_align == other.i32_align &&
                                                            self.i64_align == other.i64_align &&
                                                        self.i128_align == other.i128_align &&
                                                    self.f16_align == other.f16_align &&
                                                self.f32_align == other.f32_align &&
                                            self.f64_align == other.f64_align &&
                                        self.f128_align == other.f128_align &&
                                    self.aggregate_align == other.aggregate_align &&
                                self.vector_align == other.vector_align &&
                            self.default_address_space == other.default_address_space &&
                        self.default_address_space_pointer_spec ==
                            other.default_address_space_pointer_spec &&
                    self.address_space_info == other.address_space_info &&
                self.instruction_address_space ==
                    other.instruction_address_space &&
            self.c_enum_min_size == other.c_enum_min_size
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for TargetDataLayout {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Endian>;
        let _: ::core::cmp::AssertParamIsEq<Align>;
        let _: ::core::cmp::AssertParamIsEq<Vec<(Size, Align)>>;
        let _: ::core::cmp::AssertParamIsEq<AddressSpace>;
        let _: ::core::cmp::AssertParamIsEq<PointerSpec>;
        let _: ::core::cmp::AssertParamIsEq<Vec<(AddressSpace, PointerSpec)>>;
        let _: ::core::cmp::AssertParamIsEq<Integer>;
    }
}Eq)]
267pub struct TargetDataLayout {
268    pub endian: Endian,
269    pub i1_align: Align,
270    pub i8_align: Align,
271    pub i16_align: Align,
272    pub i32_align: Align,
273    pub i64_align: Align,
274    pub i128_align: Align,
275    pub f16_align: Align,
276    pub f32_align: Align,
277    pub f64_align: Align,
278    pub f128_align: Align,
279    pub aggregate_align: Align,
280
281    /// Alignments for vector types.
282    pub vector_align: Vec<(Size, Align)>,
283
284    pub default_address_space: AddressSpace,
285    pub default_address_space_pointer_spec: PointerSpec,
286
287    /// Address space information of all known address spaces.
288    ///
289    /// # Note
290    ///
291    /// This vector does not contain the [`PointerSpec`] relative to the default address space,
292    /// which instead lives in [`Self::default_address_space_pointer_spec`].
293    address_space_info: Vec<(AddressSpace, PointerSpec)>,
294
295    pub instruction_address_space: AddressSpace,
296
297    /// Minimum size of #[repr(C)] enums (default c_int::BITS, usually 32)
298    /// Note: This isn't in LLVM's data layout string, it is `short_enum`
299    /// so the only valid spec for LLVM is c_int::BITS or 8
300    pub c_enum_min_size: Integer,
301}
302
303impl Default for TargetDataLayout {
304    /// Creates an instance of `TargetDataLayout`.
305    fn default() -> TargetDataLayout {
306        let align = |bits| Align::from_bits(bits).unwrap();
307        TargetDataLayout {
308            endian: Endian::Big,
309            i1_align: align(8),
310            i8_align: align(8),
311            i16_align: align(16),
312            i32_align: align(32),
313            i64_align: align(32),
314            i128_align: align(32),
315            f16_align: align(16),
316            f32_align: align(32),
317            f64_align: align(64),
318            f128_align: align(128),
319            aggregate_align: align(8),
320            vector_align: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(Size::from_bits(64), align(64)),
                (Size::from_bits(128), align(128))]))vec![
321                (Size::from_bits(64), align(64)),
322                (Size::from_bits(128), align(128)),
323            ],
324            default_address_space: AddressSpace::ZERO,
325            default_address_space_pointer_spec: PointerSpec {
326                pointer_size: Size::from_bits(64),
327                pointer_align: align(64),
328                pointer_offset: Size::from_bits(64),
329                _is_fat: false,
330            },
331            address_space_info: ::alloc::vec::Vec::new()vec![],
332            instruction_address_space: AddressSpace::ZERO,
333            c_enum_min_size: Integer::I32,
334        }
335    }
336}
337
338pub enum TargetDataLayoutError<'a> {
339    InvalidAddressSpace { addr_space: &'a str, cause: &'a str, err: ParseIntError },
340    InvalidBits { kind: &'a str, bit: &'a str, cause: &'a str, err: ParseIntError },
341    MissingAlignment { cause: &'a str },
342    InvalidAlignment { cause: &'a str, err: AlignFromBytesError },
343    InconsistentTargetArchitecture { dl: &'a str, target: &'a str },
344    InconsistentTargetPointerWidth { pointer_size: u64, target: u16 },
345    InvalidBitsSize { err: String },
346    UnknownPointerSpecification { err: String },
347}
348
349#[cfg(feature = "nightly")]
350impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetDataLayoutError<'_> {
351    fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
352        match self {
353            TargetDataLayoutError::InvalidAddressSpace { addr_space, err, cause } => {
354                Diag::new(dcx, level, rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("invalid address space `{$addr_space}` for `{$cause}` in \"data-layout\": {$err}"))msg!("invalid address space `{$addr_space}` for `{$cause}` in \"data-layout\": {$err}"))
355                    .with_arg("addr_space", addr_space)
356                    .with_arg("cause", cause)
357                    .with_arg("err", err)
358            }
359            TargetDataLayoutError::InvalidBits { kind, bit, cause, err } => {
360                Diag::new(dcx, level, rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("invalid {$kind} `{$bit}` for `{$cause}` in \"data-layout\": {$err}"))msg!("invalid {$kind} `{$bit}` for `{$cause}` in \"data-layout\": {$err}"))
361                    .with_arg("kind", kind)
362                    .with_arg("bit", bit)
363                    .with_arg("cause", cause)
364                    .with_arg("err", err)
365            }
366            TargetDataLayoutError::MissingAlignment { cause } => {
367                Diag::new(dcx, level, rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("missing alignment for `{$cause}` in \"data-layout\""))msg!("missing alignment for `{$cause}` in \"data-layout\""))
368                    .with_arg("cause", cause)
369            }
370            TargetDataLayoutError::InvalidAlignment { cause, err } => {
371                Diag::new(dcx, level, rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("invalid alignment for `{$cause}` in \"data-layout\": {$err}"))msg!("invalid alignment for `{$cause}` in \"data-layout\": {$err}"))
372                    .with_arg("cause", cause)
373                    .with_arg("err", err.to_string())
374            }
375            TargetDataLayoutError::InconsistentTargetArchitecture { dl, target } => {
376                Diag::new(dcx, level, rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("inconsistent target specification: \"data-layout\" claims architecture is {$dl}-endian, while \"target-endian\" is `{$target}`"))msg!("inconsistent target specification: \"data-layout\" claims architecture is {$dl}-endian, while \"target-endian\" is `{$target}`"))
377                    .with_arg("dl", dl).with_arg("target", target)
378            }
379            TargetDataLayoutError::InconsistentTargetPointerWidth { pointer_size, target } => {
380                Diag::new(dcx, level, rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("inconsistent target specification: \"data-layout\" claims pointers are {$pointer_size}-bit, while \"target-pointer-width\" is `{$target}`"))msg!("inconsistent target specification: \"data-layout\" claims pointers are {$pointer_size}-bit, while \"target-pointer-width\" is `{$target}`"))
381                    .with_arg("pointer_size", pointer_size).with_arg("target", target)
382            }
383            TargetDataLayoutError::InvalidBitsSize { err } => {
384                Diag::new(dcx, level, rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("{$err}"))msg!("{$err}")).with_arg("err", err)
385            }
386            TargetDataLayoutError::UnknownPointerSpecification { err } => {
387                Diag::new(dcx, level, rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("unknown pointer specification `{$err}` in datalayout string"))msg!("unknown pointer specification `{$err}` in datalayout string"))
388                    .with_arg("err", err)
389            }
390        }
391    }
392}
393
394impl TargetDataLayout {
395    /// Parse data layout from an
396    /// [llvm data layout string](https://llvm.org/docs/LangRef.html#data-layout)
397    ///
398    /// This function doesn't fill `c_enum_min_size` and it will always be `I32` since it can not be
399    /// determined from llvm string.
400    pub fn parse_from_llvm_datalayout_string<'a>(
401        input: &'a str,
402        default_address_space: AddressSpace,
403    ) -> Result<TargetDataLayout, TargetDataLayoutError<'a>> {
404        // Parse an address space index from a string.
405        let parse_address_space = |s: &'a str, cause: &'a str| {
406            s.parse::<u32>().map(AddressSpace).map_err(|err| {
407                TargetDataLayoutError::InvalidAddressSpace { addr_space: s, cause, err }
408            })
409        };
410
411        // Parse a bit count from a string.
412        let parse_bits = |s: &'a str, kind: &'a str, cause: &'a str| {
413            s.parse::<u64>().map_err(|err| TargetDataLayoutError::InvalidBits {
414                kind,
415                bit: s,
416                cause,
417                err,
418            })
419        };
420
421        // Parse a size string.
422        let parse_size =
423            |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits);
424
425        // Parse an alignment string.
426        let parse_align_str = |s: &'a str, cause: &'a str| {
427            let align_from_bits = |bits| {
428                Align::from_bits(bits)
429                    .map_err(|err| TargetDataLayoutError::InvalidAlignment { cause, err })
430            };
431            let abi = parse_bits(s, "alignment", cause)?;
432            Ok(align_from_bits(abi)?)
433        };
434
435        // Parse an alignment sequence, possibly in the form `<align>[:<preferred_alignment>]`,
436        // ignoring the secondary alignment specifications.
437        let parse_align_seq = |s: &[&'a str], cause: &'a str| {
438            if s.is_empty() {
439                return Err(TargetDataLayoutError::MissingAlignment { cause });
440            }
441            parse_align_str(s[0], cause)
442        };
443
444        let mut dl = TargetDataLayout::default();
445        dl.default_address_space = default_address_space;
446
447        let mut i128_align_src = 64;
448        for spec in input.split('-') {
449            let spec_parts = spec.split(':').collect::<Vec<_>>();
450
451            match &*spec_parts {
452                ["e"] => dl.endian = Endian::Little,
453                ["E"] => dl.endian = Endian::Big,
454                [p] if p.starts_with('P') => {
455                    dl.instruction_address_space = parse_address_space(&p[1..], "P")?
456                }
457                ["a", a @ ..] => dl.aggregate_align = parse_align_seq(a, "a")?,
458                ["f16", a @ ..] => dl.f16_align = parse_align_seq(a, "f16")?,
459                ["f32", a @ ..] => dl.f32_align = parse_align_seq(a, "f32")?,
460                ["f64", a @ ..] => dl.f64_align = parse_align_seq(a, "f64")?,
461                ["f128", a @ ..] => dl.f128_align = parse_align_seq(a, "f128")?,
462                [p, s, a @ ..] if p.starts_with("p") => {
463                    let mut p = p.strip_prefix('p').unwrap();
464                    let mut _is_fat = false;
465
466                    // Some targets, such as CHERI, use the 'f' suffix in the p- spec to signal that
467                    // they use 'fat' pointers. The resulting prefix may look like `pf<addr_space>`.
468
469                    if p.starts_with('f') {
470                        p = p.strip_prefix('f').unwrap();
471                        _is_fat = true;
472                    }
473
474                    // However, we currently don't take into account further specifications:
475                    // an error is emitted instead.
476                    if p.starts_with(char::is_alphabetic) {
477                        return Err(TargetDataLayoutError::UnknownPointerSpecification {
478                            err: p.to_string(),
479                        });
480                    }
481
482                    let addr_space = if !p.is_empty() {
483                        parse_address_space(p, "p-")?
484                    } else {
485                        AddressSpace::ZERO
486                    };
487
488                    let pointer_size = parse_size(s, "p-")?;
489                    let pointer_align = parse_align_seq(a, "p-")?;
490                    let info = PointerSpec {
491                        pointer_offset: pointer_size,
492                        pointer_size,
493                        pointer_align,
494                        _is_fat,
495                    };
496                    if addr_space == default_address_space {
497                        dl.default_address_space_pointer_spec = info;
498                    } else {
499                        match dl.address_space_info.iter_mut().find(|(a, _)| *a == addr_space) {
500                            Some(e) => e.1 = info,
501                            None => {
502                                dl.address_space_info.push((addr_space, info));
503                            }
504                        }
505                    }
506                }
507                [p, s, a, _pr, i] if p.starts_with("p") => {
508                    let mut p = p.strip_prefix('p').unwrap();
509                    let mut _is_fat = false;
510
511                    // Some targets, such as CHERI, use the 'f' suffix in the p- spec to signal that
512                    // they use 'fat' pointers. The resulting prefix may look like `pf<addr_space>`.
513
514                    if p.starts_with('f') {
515                        p = p.strip_prefix('f').unwrap();
516                        _is_fat = true;
517                    }
518
519                    // However, we currently don't take into account further specifications:
520                    // an error is emitted instead.
521                    if p.starts_with(char::is_alphabetic) {
522                        return Err(TargetDataLayoutError::UnknownPointerSpecification {
523                            err: p.to_string(),
524                        });
525                    }
526
527                    let addr_space = if !p.is_empty() {
528                        parse_address_space(p, "p")?
529                    } else {
530                        AddressSpace::ZERO
531                    };
532
533                    let info = PointerSpec {
534                        pointer_size: parse_size(s, "p-")?,
535                        pointer_align: parse_align_str(a, "p-")?,
536                        pointer_offset: parse_size(i, "p-")?,
537                        _is_fat,
538                    };
539
540                    if addr_space == default_address_space {
541                        dl.default_address_space_pointer_spec = info;
542                    } else {
543                        match dl.address_space_info.iter_mut().find(|(a, _)| *a == addr_space) {
544                            Some(e) => e.1 = info,
545                            None => {
546                                dl.address_space_info.push((addr_space, info));
547                            }
548                        }
549                    }
550                }
551
552                [s, a @ ..] if s.starts_with('i') => {
553                    let Ok(bits) = s[1..].parse::<u64>() else {
554                        parse_size(&s[1..], "i")?; // For the user error.
555                        continue;
556                    };
557                    let a = parse_align_seq(a, s)?;
558                    match bits {
559                        1 => dl.i1_align = a,
560                        8 => dl.i8_align = a,
561                        16 => dl.i16_align = a,
562                        32 => dl.i32_align = a,
563                        64 => dl.i64_align = a,
564                        _ => {}
565                    }
566                    if bits >= i128_align_src && bits <= 128 {
567                        // Default alignment for i128 is decided by taking the alignment of
568                        // largest-sized i{64..=128}.
569                        i128_align_src = bits;
570                        dl.i128_align = a;
571                    }
572                }
573                [s, a @ ..] if s.starts_with('v') => {
574                    let v_size = parse_size(&s[1..], "v")?;
575                    let a = parse_align_seq(a, s)?;
576                    if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
577                        v.1 = a;
578                        continue;
579                    }
580                    // No existing entry, add a new one.
581                    dl.vector_align.push((v_size, a));
582                }
583                _ => {} // Ignore everything else.
584            }
585        }
586
587        // Inherit, if not given, address space information for specific LLVM elements from the
588        // default data address space.
589        if (dl.instruction_address_space != dl.default_address_space)
590            && dl
591                .address_space_info
592                .iter()
593                .find(|(a, _)| *a == dl.instruction_address_space)
594                .is_none()
595        {
596            dl.address_space_info.push((
597                dl.instruction_address_space,
598                dl.default_address_space_pointer_spec.clone(),
599            ));
600        }
601
602        Ok(dl)
603    }
604
605    /// Returns **exclusive** upper bound on object size in bytes, in the default data address
606    /// space.
607    ///
608    /// The theoretical maximum object size is defined as the maximum positive `isize` value.
609    /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
610    /// index every address within an object along with one byte past the end, along with allowing
611    /// `isize` to store the difference between any two pointers into an object.
612    ///
613    /// LLVM uses a 64-bit integer to represent object size in *bits*, but we care only for bytes,
614    /// so we adopt such a more-constrained size bound due to its technical limitations.
615    #[inline]
616    pub fn obj_size_bound(&self) -> u64 {
617        match self.pointer_size().bits() {
618            16 => 1 << 15,
619            32 => 1 << 31,
620            64 => 1 << 61,
621            bits => {
    ::core::panicking::panic_fmt(format_args!("obj_size_bound: unknown pointer bit size {0}",
            bits));
}panic!("obj_size_bound: unknown pointer bit size {bits}"),
622        }
623    }
624
625    /// Returns **exclusive** upper bound on object size in bytes.
626    ///
627    /// The theoretical maximum object size is defined as the maximum positive `isize` value.
628    /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
629    /// index every address within an object along with one byte past the end, along with allowing
630    /// `isize` to store the difference between any two pointers into an object.
631    ///
632    /// LLVM uses a 64-bit integer to represent object size in *bits*, but we care only for bytes,
633    /// so we adopt such a more-constrained size bound due to its technical limitations.
634    #[inline]
635    pub fn obj_size_bound_in(&self, address_space: AddressSpace) -> u64 {
636        match self.pointer_size_in(address_space).bits() {
637            16 => 1 << 15,
638            32 => 1 << 31,
639            64 => 1 << 61,
640            bits => {
    ::core::panicking::panic_fmt(format_args!("obj_size_bound: unknown pointer bit size {0}",
            bits));
}panic!("obj_size_bound: unknown pointer bit size {bits}"),
641        }
642    }
643
644    #[inline]
645    pub fn ptr_sized_integer(&self) -> Integer {
646        use Integer::*;
647        match self.pointer_offset().bits() {
648            16 => I16,
649            32 => I32,
650            64 => I64,
651            bits => {
    ::core::panicking::panic_fmt(format_args!("ptr_sized_integer: unknown pointer bit size {0}",
            bits));
}panic!("ptr_sized_integer: unknown pointer bit size {bits}"),
652        }
653    }
654
655    #[inline]
656    pub fn ptr_sized_integer_in(&self, address_space: AddressSpace) -> Integer {
657        use Integer::*;
658        match self.pointer_offset_in(address_space).bits() {
659            16 => I16,
660            32 => I32,
661            64 => I64,
662            bits => {
    ::core::panicking::panic_fmt(format_args!("ptr_sized_integer: unknown pointer bit size {0}",
            bits));
}panic!("ptr_sized_integer: unknown pointer bit size {bits}"),
663        }
664    }
665
666    /// psABI-mandated alignment for a vector type, if any
667    #[inline]
668    fn cabi_vector_align(&self, vec_size: Size) -> Option<Align> {
669        self.vector_align
670            .iter()
671            .find(|(size, _align)| *size == vec_size)
672            .map(|(_size, align)| *align)
673    }
674
675    /// an alignment resembling the one LLVM would pick for a vector
676    #[inline]
677    pub fn llvmlike_vector_align(&self, vec_size: Size) -> Align {
678        self.cabi_vector_align(vec_size)
679            .unwrap_or(Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap())
680    }
681
682    /// Get the pointer size in the default data address space.
683    #[inline]
684    pub fn pointer_size(&self) -> Size {
685        self.default_address_space_pointer_spec.pointer_size
686    }
687
688    /// Get the pointer size in a specific address space.
689    #[inline]
690    pub fn pointer_size_in(&self, c: AddressSpace) -> Size {
691        if c == self.default_address_space {
692            return self.default_address_space_pointer_spec.pointer_size;
693        }
694
695        if let Some(e) = self.address_space_info.iter().find(|(a, _)| a == &c) {
696            e.1.pointer_size
697        } else {
698            {
    ::core::panicking::panic_fmt(format_args!("Use of unknown address space {0:?}",
            c));
};panic!("Use of unknown address space {c:?}");
699        }
700    }
701
702    /// Get the pointer index in the default data address space.
703    #[inline]
704    pub fn pointer_offset(&self) -> Size {
705        self.default_address_space_pointer_spec.pointer_offset
706    }
707
708    /// Get the pointer index in a specific address space.
709    #[inline]
710    pub fn pointer_offset_in(&self, c: AddressSpace) -> Size {
711        if c == self.default_address_space {
712            return self.default_address_space_pointer_spec.pointer_offset;
713        }
714
715        if let Some(e) = self.address_space_info.iter().find(|(a, _)| a == &c) {
716            e.1.pointer_offset
717        } else {
718            {
    ::core::panicking::panic_fmt(format_args!("Use of unknown address space {0:?}",
            c));
};panic!("Use of unknown address space {c:?}");
719        }
720    }
721
722    /// Get the pointer alignment in the default data address space.
723    #[inline]
724    pub fn pointer_align(&self) -> AbiAlign {
725        AbiAlign::new(self.default_address_space_pointer_spec.pointer_align)
726    }
727
728    /// Get the pointer alignment in a specific address space.
729    #[inline]
730    pub fn pointer_align_in(&self, c: AddressSpace) -> AbiAlign {
731        AbiAlign::new(if c == self.default_address_space {
732            self.default_address_space_pointer_spec.pointer_align
733        } else if let Some(e) = self.address_space_info.iter().find(|(a, _)| a == &c) {
734            e.1.pointer_align
735        } else {
736            {
    ::core::panicking::panic_fmt(format_args!("Use of unknown address space {0:?}",
            c));
};panic!("Use of unknown address space {c:?}");
737        })
738    }
739}
740
741pub trait HasDataLayout {
742    fn data_layout(&self) -> &TargetDataLayout;
743}
744
745impl HasDataLayout for TargetDataLayout {
746    #[inline]
747    fn data_layout(&self) -> &TargetDataLayout {
748        self
749    }
750}
751
752// used by rust-analyzer
753impl HasDataLayout for &TargetDataLayout {
754    #[inline]
755    fn data_layout(&self) -> &TargetDataLayout {
756        (**self).data_layout()
757    }
758}
759
760/// Endianness of the target, which must match cfg(target-endian).
761#[derive(#[automatically_derived]
impl ::core::marker::Copy for Endian { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Endian {
    #[inline]
    fn clone(&self) -> Endian { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for Endian {
    #[inline]
    fn eq(&self, other: &Endian) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Endian {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq)]
762pub enum Endian {
763    Little,
764    Big,
765}
766
767impl Endian {
768    pub fn as_str(&self) -> &'static str {
769        match self {
770            Self::Little => "little",
771            Self::Big => "big",
772        }
773    }
774}
775
776impl fmt::Debug for Endian {
777    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
778        f.write_str(self.as_str())
779    }
780}
781
782impl FromStr for Endian {
783    type Err = String;
784
785    fn from_str(s: &str) -> Result<Self, Self::Err> {
786        match s {
787            "little" => Ok(Self::Little),
788            "big" => Ok(Self::Big),
789            _ => Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unknown endian: \"{0}\"", s))
    })format!(r#"unknown endian: "{s}""#)),
790        }
791    }
792}
793
794/// Size of a type in bytes.
795#[derive(#[automatically_derived]
impl ::core::marker::Copy for Size { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Size {
    #[inline]
    fn clone(&self) -> Size {
        let _: ::core::clone::AssertParamIsClone<u64>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for Size {
    #[inline]
    fn eq(&self, other: &Size) -> bool { self.raw == other.raw }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Size {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<u64>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for Size {
    #[inline]
    fn partial_cmp(&self, other: &Size)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::cmp::PartialOrd::partial_cmp(&self.raw, &other.raw)
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for Size {
    #[inline]
    fn cmp(&self, other: &Size) -> ::core::cmp::Ordering {
        ::core::cmp::Ord::cmp(&self.raw, &other.raw)
    }
}Ord, #[automatically_derived]
impl ::core::hash::Hash for Size {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.raw, state)
    }
}Hash)]
796#[cfg_attr(
797    feature = "nightly",
798    derive(const _: () =
    {
        impl<__E: ::rustc_serialize::Encoder>
            ::rustc_serialize::Encodable<__E> for Size {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    Size { raw: ref __binding_0 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable_NoContext, const _: () =
    {
        impl<__D: ::rustc_serialize::Decoder>
            ::rustc_serialize::Decodable<__D> for Size {
            fn decode(__decoder: &mut __D) -> Self {
                Size { raw: ::rustc_serialize::Decodable::decode(__decoder) }
            }
        }
    };Decodable_NoContext, const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for Size where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    Size { raw: ref __binding_0 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic)
799)]
800pub struct Size {
801    raw: u64,
802}
803
804#[cfg(feature = "nightly")]
805impl StableOrd for Size {
806    const CAN_USE_UNSTABLE_SORT: bool = true;
807
808    // `Ord` is implemented as just comparing numerical values and numerical values
809    // are not changed by (de-)serialization.
810    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
811}
812
813// This is debug-printed a lot in larger structs, don't waste too much space there
814impl fmt::Debug for Size {
815    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
816        f.write_fmt(format_args!("Size({0} bytes)", self.bytes()))write!(f, "Size({} bytes)", self.bytes())
817    }
818}
819
820impl Size {
821    pub const ZERO: Size = Size { raw: 0 };
822
823    /// Rounds `bits` up to the next-higher byte boundary, if `bits` is
824    /// not a multiple of 8.
825    pub fn from_bits(bits: impl TryInto<u64>) -> Size {
826        let bits = bits.try_into().ok().unwrap();
827        Size { raw: bits.div_ceil(8) }
828    }
829
830    #[inline]
831    pub fn from_bytes(bytes: impl TryInto<u64>) -> Size {
832        let bytes: u64 = bytes.try_into().ok().unwrap();
833        Size { raw: bytes }
834    }
835
836    #[inline]
837    pub fn bytes(self) -> u64 {
838        self.raw
839    }
840
841    #[inline]
842    pub fn bytes_usize(self) -> usize {
843        self.bytes().try_into().unwrap()
844    }
845
846    #[inline]
847    pub fn bits(self) -> u64 {
848        #[cold]
849        fn overflow(bytes: u64) -> ! {
850            {
    ::core::panicking::panic_fmt(format_args!("Size::bits: {0} bytes in bits doesn\'t fit in u64",
            bytes));
}panic!("Size::bits: {bytes} bytes in bits doesn't fit in u64")
851        }
852
853        self.bytes().checked_mul(8).unwrap_or_else(|| overflow(self.bytes()))
854    }
855
856    #[inline]
857    pub fn bits_usize(self) -> usize {
858        self.bits().try_into().unwrap()
859    }
860
861    #[inline]
862    pub fn align_to(self, align: Align) -> Size {
863        let mask = align.bytes() - 1;
864        Size::from_bytes((self.bytes() + mask) & !mask)
865    }
866
867    #[inline]
868    pub fn is_aligned(self, align: Align) -> bool {
869        let mask = align.bytes() - 1;
870        self.bytes() & mask == 0
871    }
872
873    #[inline]
874    pub fn checked_add<C: HasDataLayout>(self, offset: Size, cx: &C) -> Option<Size> {
875        let dl = cx.data_layout();
876
877        let bytes = self.bytes().checked_add(offset.bytes())?;
878
879        if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None }
880    }
881
882    #[inline]
883    pub fn checked_mul<C: HasDataLayout>(self, count: u64, cx: &C) -> Option<Size> {
884        let dl = cx.data_layout();
885
886        let bytes = self.bytes().checked_mul(count)?;
887        if bytes < dl.obj_size_bound() { Some(Size::from_bytes(bytes)) } else { None }
888    }
889
890    /// Truncates `value` to `self` bits and then sign-extends it to 128 bits
891    /// (i.e., if it is negative, fill with 1's on the left).
892    #[inline]
893    pub fn sign_extend(self, value: u128) -> i128 {
894        let size = self.bits();
895        if size == 0 {
896            // Truncated until nothing is left.
897            return 0;
898        }
899        // Sign-extend it.
900        let shift = 128 - size;
901        // Shift the unsigned value to the left, then shift back to the right as signed
902        // (essentially fills with sign bit on the left).
903        ((value << shift) as i128) >> shift
904    }
905
906    /// Truncates `value` to `self` bits.
907    #[inline]
908    pub fn truncate(self, value: u128) -> u128 {
909        let size = self.bits();
910        if size == 0 {
911            // Truncated until nothing is left.
912            return 0;
913        }
914        let shift = 128 - size;
915        // Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
916        (value << shift) >> shift
917    }
918
919    #[inline]
920    pub fn signed_int_min(&self) -> i128 {
921        self.sign_extend(1_u128 << (self.bits() - 1))
922    }
923
924    #[inline]
925    pub fn signed_int_max(&self) -> i128 {
926        i128::MAX >> (128 - self.bits())
927    }
928
929    #[inline]
930    pub fn unsigned_int_max(&self) -> u128 {
931        u128::MAX >> (128 - self.bits())
932    }
933}
934
935// Panicking addition, subtraction and multiplication for convenience.
936// Avoid during layout computation, return `LayoutError` instead.
937
938impl Add for Size {
939    type Output = Size;
940    #[inline]
941    fn add(self, other: Size) -> Size {
942        Size::from_bytes(self.bytes().checked_add(other.bytes()).unwrap_or_else(|| {
943            {
    ::core::panicking::panic_fmt(format_args!("Size::add: {0} + {1} doesn\'t fit in u64",
            self.bytes(), other.bytes()));
}panic!("Size::add: {} + {} doesn't fit in u64", self.bytes(), other.bytes())
944        }))
945    }
946}
947
948impl Sub for Size {
949    type Output = Size;
950    #[inline]
951    fn sub(self, other: Size) -> Size {
952        Size::from_bytes(self.bytes().checked_sub(other.bytes()).unwrap_or_else(|| {
953            {
    ::core::panicking::panic_fmt(format_args!("Size::sub: {0} - {1} would result in negative size",
            self.bytes(), other.bytes()));
}panic!("Size::sub: {} - {} would result in negative size", self.bytes(), other.bytes())
954        }))
955    }
956}
957
958impl Mul<Size> for u64 {
959    type Output = Size;
960    #[inline]
961    fn mul(self, size: Size) -> Size {
962        size * self
963    }
964}
965
966impl Mul<u64> for Size {
967    type Output = Size;
968    #[inline]
969    fn mul(self, count: u64) -> Size {
970        match self.bytes().checked_mul(count) {
971            Some(bytes) => Size::from_bytes(bytes),
972            None => {
    ::core::panicking::panic_fmt(format_args!("Size::mul: {0} * {1} doesn\'t fit in u64",
            self.bytes(), count));
}panic!("Size::mul: {} * {} doesn't fit in u64", self.bytes(), count),
973        }
974    }
975}
976
977impl AddAssign for Size {
978    #[inline]
979    fn add_assign(&mut self, other: Size) {
980        *self = *self + other;
981    }
982}
983
984#[cfg(feature = "nightly")]
985impl Step for Size {
986    #[inline]
987    fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
988        u64::steps_between(&start.bytes(), &end.bytes())
989    }
990
991    #[inline]
992    fn forward_checked(start: Self, count: usize) -> Option<Self> {
993        u64::forward_checked(start.bytes(), count).map(Self::from_bytes)
994    }
995
996    #[inline]
997    fn forward(start: Self, count: usize) -> Self {
998        Self::from_bytes(u64::forward(start.bytes(), count))
999    }
1000
1001    #[inline]
1002    unsafe fn forward_unchecked(start: Self, count: usize) -> Self {
1003        Self::from_bytes(unsafe { u64::forward_unchecked(start.bytes(), count) })
1004    }
1005
1006    #[inline]
1007    fn backward_checked(start: Self, count: usize) -> Option<Self> {
1008        u64::backward_checked(start.bytes(), count).map(Self::from_bytes)
1009    }
1010
1011    #[inline]
1012    fn backward(start: Self, count: usize) -> Self {
1013        Self::from_bytes(u64::backward(start.bytes(), count))
1014    }
1015
1016    #[inline]
1017    unsafe fn backward_unchecked(start: Self, count: usize) -> Self {
1018        Self::from_bytes(unsafe { u64::backward_unchecked(start.bytes(), count) })
1019    }
1020}
1021
1022/// Alignment of a type in bytes (always a power of two).
1023#[derive(#[automatically_derived]
impl ::core::marker::Copy for Align { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Align {
    #[inline]
    fn clone(&self) -> Align {
        let _: ::core::clone::AssertParamIsClone<u8>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for Align {
    #[inline]
    fn eq(&self, other: &Align) -> bool { self.pow2 == other.pow2 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Align {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<u8>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for Align {
    #[inline]
    fn partial_cmp(&self, other: &Align)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::cmp::PartialOrd::partial_cmp(&self.pow2, &other.pow2)
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for Align {
    #[inline]
    fn cmp(&self, other: &Align) -> ::core::cmp::Ordering {
        ::core::cmp::Ord::cmp(&self.pow2, &other.pow2)
    }
}Ord, #[automatically_derived]
impl ::core::hash::Hash for Align {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.pow2, state)
    }
}Hash)]
1024#[cfg_attr(
1025    feature = "nightly",
1026    derive(const _: () =
    {
        impl<__E: ::rustc_serialize::Encoder>
            ::rustc_serialize::Encodable<__E> for Align {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    Align { pow2: ref __binding_0 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable_NoContext, const _: () =
    {
        impl<__D: ::rustc_serialize::Decoder>
            ::rustc_serialize::Decodable<__D> for Align {
            fn decode(__decoder: &mut __D) -> Self {
                Align {
                    pow2: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable_NoContext, const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for Align where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    Align { pow2: ref __binding_0 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic)
1027)]
1028pub struct Align {
1029    pow2: u8,
1030}
1031
1032// This is debug-printed a lot in larger structs, don't waste too much space there
1033impl fmt::Debug for Align {
1034    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1035        f.write_fmt(format_args!("Align({0} bytes)", self.bytes()))write!(f, "Align({} bytes)", self.bytes())
1036    }
1037}
1038
1039#[derive(#[automatically_derived]
impl ::core::clone::Clone for AlignFromBytesError {
    #[inline]
    fn clone(&self) -> AlignFromBytesError {
        let _: ::core::clone::AssertParamIsClone<u64>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for AlignFromBytesError { }Copy)]
1040pub enum AlignFromBytesError {
1041    NotPowerOfTwo(u64),
1042    TooLarge(u64),
1043}
1044
1045impl fmt::Debug for AlignFromBytesError {
1046    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1047        fmt::Display::fmt(self, f)
1048    }
1049}
1050
1051impl fmt::Display for AlignFromBytesError {
1052    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1053        match self {
1054            AlignFromBytesError::NotPowerOfTwo(align) => f.write_fmt(format_args!("{0} is not a power of 2", align))write!(f, "{align} is not a power of 2"),
1055            AlignFromBytesError::TooLarge(align) => f.write_fmt(format_args!("{0} is too large", align))write!(f, "{align} is too large"),
1056        }
1057    }
1058}
1059
1060impl Align {
1061    pub const ONE: Align = Align { pow2: 0 };
1062    pub const EIGHT: Align = Align { pow2: 3 };
1063    // LLVM has a maximal supported alignment of 2^29, we inherit that.
1064    pub const MAX: Align = Align { pow2: 29 };
1065
1066    /// Either `1 << (pointer_bits - 1)` or [`Align::MAX`], whichever is smaller.
1067    #[inline]
1068    pub fn max_for_target(tdl: &TargetDataLayout) -> Align {
1069        let pointer_bits = tdl.pointer_size().bits();
1070        if let Ok(pointer_bits) = u8::try_from(pointer_bits)
1071            && pointer_bits <= Align::MAX.pow2
1072        {
1073            Align { pow2: pointer_bits - 1 }
1074        } else {
1075            Align::MAX
1076        }
1077    }
1078
1079    #[inline]
1080    pub fn from_bits(bits: u64) -> Result<Align, AlignFromBytesError> {
1081        Align::from_bytes(Size::from_bits(bits).bytes())
1082    }
1083
1084    #[inline]
1085    pub const fn from_bytes(align: u64) -> Result<Align, AlignFromBytesError> {
1086        // Treat an alignment of 0 bytes like 1-byte alignment.
1087        if align == 0 {
1088            return Ok(Align::ONE);
1089        }
1090
1091        #[cold]
1092        const fn not_power_of_2(align: u64) -> AlignFromBytesError {
1093            AlignFromBytesError::NotPowerOfTwo(align)
1094        }
1095
1096        #[cold]
1097        const fn too_large(align: u64) -> AlignFromBytesError {
1098            AlignFromBytesError::TooLarge(align)
1099        }
1100
1101        let tz = align.trailing_zeros();
1102        if align != (1 << tz) {
1103            return Err(not_power_of_2(align));
1104        }
1105
1106        let pow2 = tz as u8;
1107        if pow2 > Self::MAX.pow2 {
1108            return Err(too_large(align));
1109        }
1110
1111        Ok(Align { pow2 })
1112    }
1113
1114    #[inline]
1115    pub const fn bytes(self) -> u64 {
1116        1 << self.pow2
1117    }
1118
1119    #[inline]
1120    pub fn bytes_usize(self) -> usize {
1121        self.bytes().try_into().unwrap()
1122    }
1123
1124    #[inline]
1125    pub const fn bits(self) -> u64 {
1126        self.bytes() * 8
1127    }
1128
1129    #[inline]
1130    pub fn bits_usize(self) -> usize {
1131        self.bits().try_into().unwrap()
1132    }
1133
1134    /// Obtain the greatest factor of `size` that is an alignment
1135    /// (the largest power of two the Size is a multiple of).
1136    ///
1137    /// Note that all numbers are factors of 0
1138    #[inline]
1139    pub fn max_aligned_factor(size: Size) -> Align {
1140        Align { pow2: size.bytes().trailing_zeros() as u8 }
1141    }
1142
1143    /// Reduces Align to an aligned factor of `size`.
1144    #[inline]
1145    pub fn restrict_for_offset(self, size: Size) -> Align {
1146        self.min(Align::max_aligned_factor(size))
1147    }
1148}
1149
1150/// A pair of alignments, ABI-mandated and preferred.
1151///
1152/// The "preferred" alignment is an LLVM concept that is virtually meaningless to Rust code:
1153/// it is not exposed semantically to programmers nor can they meaningfully affect it.
1154/// The only concern for us is that preferred alignment must not be less than the mandated alignment
1155/// and thus in practice the two values are almost always identical.
1156///
1157/// An example of a rare thing actually affected by preferred alignment is aligning of statics.
1158/// It is of effectively no consequence for layout in structs and on the stack.
1159#[derive(#[automatically_derived]
impl ::core::marker::Copy for AbiAlign { }Copy, #[automatically_derived]
impl ::core::clone::Clone for AbiAlign {
    #[inline]
    fn clone(&self) -> AbiAlign {
        let _: ::core::clone::AssertParamIsClone<Align>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for AbiAlign {
    #[inline]
    fn eq(&self, other: &AbiAlign) -> bool { self.abi == other.abi }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for AbiAlign {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Align>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for AbiAlign {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.abi, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for AbiAlign {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f, "AbiAlign",
            "abi", &&self.abi)
    }
}Debug)]
1160#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for AbiAlign where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    AbiAlign { abi: ref __binding_0 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic))]
1161pub struct AbiAlign {
1162    pub abi: Align,
1163}
1164
1165impl AbiAlign {
1166    #[inline]
1167    pub fn new(align: Align) -> AbiAlign {
1168        AbiAlign { abi: align }
1169    }
1170
1171    #[inline]
1172    pub fn min(self, other: AbiAlign) -> AbiAlign {
1173        AbiAlign { abi: self.abi.min(other.abi) }
1174    }
1175
1176    #[inline]
1177    pub fn max(self, other: AbiAlign) -> AbiAlign {
1178        AbiAlign { abi: self.abi.max(other.abi) }
1179    }
1180}
1181
1182impl Deref for AbiAlign {
1183    type Target = Align;
1184
1185    fn deref(&self) -> &Self::Target {
1186        &self.abi
1187    }
1188}
1189
1190/// Integers, also used for enum discriminants.
1191#[derive(#[automatically_derived]
impl ::core::marker::Copy for Integer { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Integer {
    #[inline]
    fn clone(&self) -> Integer { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for Integer {
    #[inline]
    fn eq(&self, other: &Integer) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Integer {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for Integer {
    #[inline]
    fn partial_cmp(&self, other: &Integer)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for Integer {
    #[inline]
    fn cmp(&self, other: &Integer) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
    }
}Ord, #[automatically_derived]
impl ::core::hash::Hash for Integer {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Integer {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                Integer::I8 => "I8",
                Integer::I16 => "I16",
                Integer::I32 => "I32",
                Integer::I64 => "I64",
                Integer::I128 => "I128",
            })
    }
}Debug)]
1192#[cfg_attr(
1193    feature = "nightly",
1194    derive(const _: () =
    {
        impl<__E: ::rustc_serialize::Encoder>
            ::rustc_serialize::Encodable<__E> for Integer {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        Integer::I8 => { 0usize }
                        Integer::I16 => { 1usize }
                        Integer::I32 => { 2usize }
                        Integer::I64 => { 3usize }
                        Integer::I128 => { 4usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    Integer::I8 => {}
                    Integer::I16 => {}
                    Integer::I32 => {}
                    Integer::I64 => {}
                    Integer::I128 => {}
                }
            }
        }
    };Encodable_NoContext, const _: () =
    {
        impl<__D: ::rustc_serialize::Decoder>
            ::rustc_serialize::Decodable<__D> for Integer {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { Integer::I8 }
                    1usize => { Integer::I16 }
                    2usize => { Integer::I32 }
                    3usize => { Integer::I64 }
                    4usize => { Integer::I128 }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Integer`, expected 0..5, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable_NoContext, const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for Integer where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    Integer::I8 => {}
                    Integer::I16 => {}
                    Integer::I32 => {}
                    Integer::I64 => {}
                    Integer::I128 => {}
                }
            }
        }
    };HashStable_Generic)
1195)]
1196pub enum Integer {
1197    I8,
1198    I16,
1199    I32,
1200    I64,
1201    I128,
1202}
1203
1204impl Integer {
1205    pub fn int_ty_str(self) -> &'static str {
1206        use Integer::*;
1207        match self {
1208            I8 => "i8",
1209            I16 => "i16",
1210            I32 => "i32",
1211            I64 => "i64",
1212            I128 => "i128",
1213        }
1214    }
1215
1216    pub fn uint_ty_str(self) -> &'static str {
1217        use Integer::*;
1218        match self {
1219            I8 => "u8",
1220            I16 => "u16",
1221            I32 => "u32",
1222            I64 => "u64",
1223            I128 => "u128",
1224        }
1225    }
1226
1227    #[inline]
1228    pub fn size(self) -> Size {
1229        use Integer::*;
1230        match self {
1231            I8 => Size::from_bytes(1),
1232            I16 => Size::from_bytes(2),
1233            I32 => Size::from_bytes(4),
1234            I64 => Size::from_bytes(8),
1235            I128 => Size::from_bytes(16),
1236        }
1237    }
1238
1239    /// Gets the Integer type from an IntegerType.
1240    pub fn from_attr<C: HasDataLayout>(cx: &C, ity: IntegerType) -> Integer {
1241        let dl = cx.data_layout();
1242
1243        match ity {
1244            IntegerType::Pointer(_) => dl.ptr_sized_integer(),
1245            IntegerType::Fixed(x, _) => x,
1246        }
1247    }
1248
1249    pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAlign {
1250        use Integer::*;
1251        let dl = cx.data_layout();
1252
1253        AbiAlign::new(match self {
1254            I8 => dl.i8_align,
1255            I16 => dl.i16_align,
1256            I32 => dl.i32_align,
1257            I64 => dl.i64_align,
1258            I128 => dl.i128_align,
1259        })
1260    }
1261
1262    /// Returns the largest signed value that can be represented by this Integer.
1263    #[inline]
1264    pub fn signed_max(self) -> i128 {
1265        use Integer::*;
1266        match self {
1267            I8 => i8::MAX as i128,
1268            I16 => i16::MAX as i128,
1269            I32 => i32::MAX as i128,
1270            I64 => i64::MAX as i128,
1271            I128 => i128::MAX,
1272        }
1273    }
1274
1275    /// Returns the smallest signed value that can be represented by this Integer.
1276    #[inline]
1277    pub fn signed_min(self) -> i128 {
1278        use Integer::*;
1279        match self {
1280            I8 => i8::MIN as i128,
1281            I16 => i16::MIN as i128,
1282            I32 => i32::MIN as i128,
1283            I64 => i64::MIN as i128,
1284            I128 => i128::MIN,
1285        }
1286    }
1287
1288    /// Finds the smallest Integer type which can represent the signed value.
1289    #[inline]
1290    pub fn fit_signed(x: i128) -> Integer {
1291        use Integer::*;
1292        match x {
1293            -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8,
1294            -0x0000_0000_0000_8000..=0x0000_0000_0000_7fff => I16,
1295            -0x0000_0000_8000_0000..=0x0000_0000_7fff_ffff => I32,
1296            -0x8000_0000_0000_0000..=0x7fff_ffff_ffff_ffff => I64,
1297            _ => I128,
1298        }
1299    }
1300
1301    /// Finds the smallest Integer type which can represent the unsigned value.
1302    #[inline]
1303    pub fn fit_unsigned(x: u128) -> Integer {
1304        use Integer::*;
1305        match x {
1306            0..=0x0000_0000_0000_00ff => I8,
1307            0..=0x0000_0000_0000_ffff => I16,
1308            0..=0x0000_0000_ffff_ffff => I32,
1309            0..=0xffff_ffff_ffff_ffff => I64,
1310            _ => I128,
1311        }
1312    }
1313
1314    /// Finds the smallest integer with the given alignment.
1315    pub fn for_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Option<Integer> {
1316        use Integer::*;
1317        let dl = cx.data_layout();
1318
1319        [I8, I16, I32, I64, I128].into_iter().find(|&candidate| {
1320            wanted == candidate.align(dl).abi && wanted.bytes() == candidate.size().bytes()
1321        })
1322    }
1323
1324    /// Find the largest integer with the given alignment or less.
1325    pub fn approximate_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Integer {
1326        use Integer::*;
1327        let dl = cx.data_layout();
1328
1329        // FIXME(eddyb) maybe include I128 in the future, when it works everywhere.
1330        for candidate in [I64, I32, I16] {
1331            if wanted >= candidate.align(dl).abi && wanted.bytes() >= candidate.size().bytes() {
1332                return candidate;
1333            }
1334        }
1335        I8
1336    }
1337
1338    // FIXME(eddyb) consolidate this and other methods that find the appropriate
1339    // `Integer` given some requirements.
1340    #[inline]
1341    pub fn from_size(size: Size) -> Result<Self, String> {
1342        match size.bits() {
1343            8 => Ok(Integer::I8),
1344            16 => Ok(Integer::I16),
1345            32 => Ok(Integer::I32),
1346            64 => Ok(Integer::I64),
1347            128 => Ok(Integer::I128),
1348            _ => Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("rust does not support integers with {0} bits",
                size.bits()))
    })format!("rust does not support integers with {} bits", size.bits())),
1349        }
1350    }
1351}
1352
1353/// Floating-point types.
1354#[derive(#[automatically_derived]
impl ::core::marker::Copy for Float { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Float {
    #[inline]
    fn clone(&self) -> Float { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for Float {
    #[inline]
    fn eq(&self, other: &Float) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Float {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for Float {
    #[inline]
    fn partial_cmp(&self, other: &Float)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for Float {
    #[inline]
    fn cmp(&self, other: &Float) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
    }
}Ord, #[automatically_derived]
impl ::core::hash::Hash for Float {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Float {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                Float::F16 => "F16",
                Float::F32 => "F32",
                Float::F64 => "F64",
                Float::F128 => "F128",
            })
    }
}Debug)]
1355#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for Float where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    Float::F16 => {}
                    Float::F32 => {}
                    Float::F64 => {}
                    Float::F128 => {}
                }
            }
        }
    };HashStable_Generic))]
1356pub enum Float {
1357    F16,
1358    F32,
1359    F64,
1360    F128,
1361}
1362
1363impl Float {
1364    pub fn size(self) -> Size {
1365        use Float::*;
1366
1367        match self {
1368            F16 => Size::from_bits(16),
1369            F32 => Size::from_bits(32),
1370            F64 => Size::from_bits(64),
1371            F128 => Size::from_bits(128),
1372        }
1373    }
1374
1375    pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAlign {
1376        use Float::*;
1377        let dl = cx.data_layout();
1378
1379        AbiAlign::new(match self {
1380            F16 => dl.f16_align,
1381            F32 => dl.f32_align,
1382            F64 => dl.f64_align,
1383            F128 => dl.f128_align,
1384        })
1385    }
1386}
1387
1388/// Fundamental unit of memory access and layout.
1389#[derive(#[automatically_derived]
impl ::core::marker::Copy for Primitive { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Primitive {
    #[inline]
    fn clone(&self) -> Primitive {
        let _: ::core::clone::AssertParamIsClone<Integer>;
        let _: ::core::clone::AssertParamIsClone<bool>;
        let _: ::core::clone::AssertParamIsClone<Float>;
        let _: ::core::clone::AssertParamIsClone<AddressSpace>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for Primitive {
    #[inline]
    fn eq(&self, other: &Primitive) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (Primitive::Int(__self_0, __self_1),
                    Primitive::Int(__arg1_0, __arg1_1)) =>
                    __self_1 == __arg1_1 && __self_0 == __arg1_0,
                (Primitive::Float(__self_0), Primitive::Float(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Primitive::Pointer(__self_0), Primitive::Pointer(__arg1_0))
                    => __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Primitive {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Integer>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
        let _: ::core::cmp::AssertParamIsEq<Float>;
        let _: ::core::cmp::AssertParamIsEq<AddressSpace>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for Primitive {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            Primitive::Int(__self_0, __self_1) => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state)
            }
            Primitive::Float(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            Primitive::Pointer(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
        }
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Primitive {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Primitive::Int(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f, "Int",
                    __self_0, &__self_1),
            Primitive::Float(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Float",
                    &__self_0),
            Primitive::Pointer(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Pointer", &__self_0),
        }
    }
}Debug)]
1390#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for Primitive where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    Primitive::Int(ref __binding_0, ref __binding_1) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                    }
                    Primitive::Float(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    Primitive::Pointer(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic))]
1391pub enum Primitive {
1392    /// The `bool` is the signedness of the `Integer` type.
1393    ///
1394    /// One would think we would not care about such details this low down,
1395    /// but some ABIs are described in terms of C types and ISAs where the
1396    /// integer arithmetic is done on {sign,zero}-extended registers, e.g.
1397    /// a negative integer passed by zero-extension will appear positive in
1398    /// the callee, and most operations on it will produce the wrong values.
1399    Int(Integer, bool),
1400    Float(Float),
1401    Pointer(AddressSpace),
1402}
1403
1404impl Primitive {
1405    pub fn size<C: HasDataLayout>(self, cx: &C) -> Size {
1406        use Primitive::*;
1407        let dl = cx.data_layout();
1408
1409        match self {
1410            Int(i, _) => i.size(),
1411            Float(f) => f.size(),
1412            Pointer(a) => dl.pointer_size_in(a),
1413        }
1414    }
1415
1416    pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAlign {
1417        use Primitive::*;
1418        let dl = cx.data_layout();
1419
1420        match self {
1421            Int(i, _) => i.align(dl),
1422            Float(f) => f.align(dl),
1423            Pointer(a) => dl.pointer_align_in(a),
1424        }
1425    }
1426}
1427
1428/// Inclusive wrap-around range of valid values, that is, if
1429/// start > end, it represents `start..=MAX`, followed by `0..=end`.
1430///
1431/// That is, for an i8 primitive, a range of `254..=2` means following
1432/// sequence:
1433///
1434///    254 (-2), 255 (-1), 0, 1, 2
1435///
1436/// This is intended specifically to mirror LLVM’s `!range` metadata semantics.
1437#[derive(#[automatically_derived]
impl ::core::clone::Clone for WrappingRange {
    #[inline]
    fn clone(&self) -> WrappingRange {
        let _: ::core::clone::AssertParamIsClone<u128>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for WrappingRange { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for WrappingRange {
    #[inline]
    fn eq(&self, other: &WrappingRange) -> bool {
        self.start == other.start && self.end == other.end
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for WrappingRange {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<u128>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for WrappingRange {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.start, state);
        ::core::hash::Hash::hash(&self.end, state)
    }
}Hash)]
1438#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for WrappingRange where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    WrappingRange { start: ref __binding_0, end: ref __binding_1
                        } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic))]
1439pub struct WrappingRange {
1440    pub start: u128,
1441    pub end: u128,
1442}
1443
1444impl WrappingRange {
1445    pub fn full(size: Size) -> Self {
1446        Self { start: 0, end: size.unsigned_int_max() }
1447    }
1448
1449    /// Returns `true` if `v` is contained in the range.
1450    #[inline(always)]
1451    pub fn contains(&self, v: u128) -> bool {
1452        if self.start <= self.end {
1453            self.start <= v && v <= self.end
1454        } else {
1455            self.start <= v || v <= self.end
1456        }
1457    }
1458
1459    /// Returns `true` if all the values in `other` are contained in this range,
1460    /// when the values are considered as having width `size`.
1461    #[inline(always)]
1462    pub fn contains_range(&self, other: Self, size: Size) -> bool {
1463        if self.is_full_for(size) {
1464            true
1465        } else {
1466            let trunc = |x| size.truncate(x);
1467
1468            let delta = self.start;
1469            let max = trunc(self.end.wrapping_sub(delta));
1470
1471            let other_start = trunc(other.start.wrapping_sub(delta));
1472            let other_end = trunc(other.end.wrapping_sub(delta));
1473
1474            // Having shifted both input ranges by `delta`, now we only need to check
1475            // whether `0..=max` contains `other_start..=other_end`, which can only
1476            // happen if the other doesn't wrap since `self` isn't everything.
1477            (other_start <= other_end) && (other_end <= max)
1478        }
1479    }
1480
1481    /// Returns `self` with replaced `start`
1482    #[inline(always)]
1483    fn with_start(mut self, start: u128) -> Self {
1484        self.start = start;
1485        self
1486    }
1487
1488    /// Returns `self` with replaced `end`
1489    #[inline(always)]
1490    fn with_end(mut self, end: u128) -> Self {
1491        self.end = end;
1492        self
1493    }
1494
1495    /// Returns `true` if `size` completely fills the range.
1496    ///
1497    /// Note that this is *not* the same as `self == WrappingRange::full(size)`.
1498    /// Niche calculations can produce full ranges which are not the canonical one;
1499    /// for example `Option<NonZero<u16>>` gets `valid_range: (..=0) | (1..)`.
1500    #[inline]
1501    fn is_full_for(&self, size: Size) -> bool {
1502        let max_value = size.unsigned_int_max();
1503        if true {
    if !(self.start <= max_value && self.end <= max_value) {
        ::core::panicking::panic("assertion failed: self.start <= max_value && self.end <= max_value")
    };
};debug_assert!(self.start <= max_value && self.end <= max_value);
1504        self.start == (self.end.wrapping_add(1) & max_value)
1505    }
1506
1507    /// Checks whether this range is considered non-wrapping when the values are
1508    /// interpreted as *unsigned* numbers of width `size`.
1509    ///
1510    /// Returns `Ok(true)` if there's no wrap-around, `Ok(false)` if there is,
1511    /// and `Err(..)` if the range is full so it depends how you think about it.
1512    #[inline]
1513    pub fn no_unsigned_wraparound(&self, size: Size) -> Result<bool, RangeFull> {
1514        if self.is_full_for(size) { Err(..) } else { Ok(self.start <= self.end) }
1515    }
1516
1517    /// Checks whether this range is considered non-wrapping when the values are
1518    /// interpreted as *signed* numbers of width `size`.
1519    ///
1520    /// This is heavily dependent on the `size`, as `100..=200` does wrap when
1521    /// interpreted as `i8`, but doesn't when interpreted as `i16`.
1522    ///
1523    /// Returns `Ok(true)` if there's no wrap-around, `Ok(false)` if there is,
1524    /// and `Err(..)` if the range is full so it depends how you think about it.
1525    #[inline]
1526    pub fn no_signed_wraparound(&self, size: Size) -> Result<bool, RangeFull> {
1527        if self.is_full_for(size) {
1528            Err(..)
1529        } else {
1530            let start: i128 = size.sign_extend(self.start);
1531            let end: i128 = size.sign_extend(self.end);
1532            Ok(start <= end)
1533        }
1534    }
1535}
1536
1537impl fmt::Debug for WrappingRange {
1538    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1539        if self.start > self.end {
1540            fmt.write_fmt(format_args!("(..={0}) | ({1}..)", self.end, self.start))write!(fmt, "(..={}) | ({}..)", self.end, self.start)?;
1541        } else {
1542            fmt.write_fmt(format_args!("{0}..={1}", self.start, self.end))write!(fmt, "{}..={}", self.start, self.end)?;
1543        }
1544        Ok(())
1545    }
1546}
1547
1548/// Information about one scalar component of a Rust type.
1549#[derive(#[automatically_derived]
impl ::core::clone::Clone for Scalar {
    #[inline]
    fn clone(&self) -> Scalar {
        let _: ::core::clone::AssertParamIsClone<Primitive>;
        let _: ::core::clone::AssertParamIsClone<WrappingRange>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Scalar { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for Scalar {
    #[inline]
    fn eq(&self, other: &Scalar) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (Scalar::Initialized { value: __self_0, valid_range: __self_1
                    }, Scalar::Initialized {
                    value: __arg1_0, valid_range: __arg1_1 }) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                (Scalar::Union { value: __self_0 }, Scalar::Union {
                    value: __arg1_0 }) => __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Scalar {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Primitive>;
        let _: ::core::cmp::AssertParamIsEq<WrappingRange>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for Scalar {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            Scalar::Initialized { value: __self_0, valid_range: __self_1 } =>
                {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state)
            }
            Scalar::Union { value: __self_0 } =>
                ::core::hash::Hash::hash(__self_0, state),
        }
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Scalar {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Scalar::Initialized { value: __self_0, valid_range: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "Initialized", "value", __self_0, "valid_range", &__self_1),
            Scalar::Union { value: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f, "Union",
                    "value", &__self_0),
        }
    }
}Debug)]
1550#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for Scalar where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    Scalar::Initialized {
                        value: ref __binding_0, valid_range: ref __binding_1 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                    }
                    Scalar::Union { value: ref __binding_0 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic))]
1551pub enum Scalar {
1552    Initialized {
1553        value: Primitive,
1554
1555        // FIXME(eddyb) always use the shortest range, e.g., by finding
1556        // the largest space between two consecutive valid values and
1557        // taking everything else as the (shortest) valid range.
1558        valid_range: WrappingRange,
1559    },
1560    Union {
1561        /// Even for unions, we need to use the correct registers for the kind of
1562        /// values inside the union, so we keep the `Primitive` type around. We
1563        /// also use it to compute the size of the scalar.
1564        /// However, unions never have niches and even allow undef,
1565        /// so there is no `valid_range`.
1566        value: Primitive,
1567    },
1568}
1569
1570impl Scalar {
1571    #[inline]
1572    pub fn is_bool(&self) -> bool {
1573        use Integer::*;
1574        #[allow(non_exhaustive_omitted_patterns)] match self {
    Scalar::Initialized {
        value: Primitive::Int(I8, false),
        valid_range: WrappingRange { start: 0, end: 1 } } => true,
    _ => false,
}matches!(
1575            self,
1576            Scalar::Initialized {
1577                value: Primitive::Int(I8, false),
1578                valid_range: WrappingRange { start: 0, end: 1 }
1579            }
1580        )
1581    }
1582
1583    /// Get the primitive representation of this type, ignoring the valid range and whether the
1584    /// value is allowed to be undefined (due to being a union).
1585    pub fn primitive(&self) -> Primitive {
1586        match *self {
1587            Scalar::Initialized { value, .. } | Scalar::Union { value } => value,
1588        }
1589    }
1590
1591    pub fn align(self, cx: &impl HasDataLayout) -> AbiAlign {
1592        self.primitive().align(cx)
1593    }
1594
1595    pub fn size(self, cx: &impl HasDataLayout) -> Size {
1596        self.primitive().size(cx)
1597    }
1598
1599    #[inline]
1600    pub fn to_union(&self) -> Self {
1601        Self::Union { value: self.primitive() }
1602    }
1603
1604    #[inline]
1605    pub fn valid_range(&self, cx: &impl HasDataLayout) -> WrappingRange {
1606        match *self {
1607            Scalar::Initialized { valid_range, .. } => valid_range,
1608            Scalar::Union { value } => WrappingRange::full(value.size(cx)),
1609        }
1610    }
1611
1612    #[inline]
1613    /// Allows the caller to mutate the valid range. This operation will panic if attempted on a
1614    /// union.
1615    pub fn valid_range_mut(&mut self) -> &mut WrappingRange {
1616        match self {
1617            Scalar::Initialized { valid_range, .. } => valid_range,
1618            Scalar::Union { .. } => {
    ::core::panicking::panic_fmt(format_args!("cannot change the valid range of a union"));
}panic!("cannot change the valid range of a union"),
1619        }
1620    }
1621
1622    /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole
1623    /// layout.
1624    #[inline]
1625    pub fn is_always_valid<C: HasDataLayout>(&self, cx: &C) -> bool {
1626        match *self {
1627            Scalar::Initialized { valid_range, .. } => valid_range.is_full_for(self.size(cx)),
1628            Scalar::Union { .. } => true,
1629        }
1630    }
1631
1632    /// Returns `true` if this type can be left uninit.
1633    #[inline]
1634    pub fn is_uninit_valid(&self) -> bool {
1635        match *self {
1636            Scalar::Initialized { .. } => false,
1637            Scalar::Union { .. } => true,
1638        }
1639    }
1640
1641    /// Returns `true` if this is a signed integer scalar
1642    #[inline]
1643    pub fn is_signed(&self) -> bool {
1644        match self.primitive() {
1645            Primitive::Int(_, signed) => signed,
1646            _ => false,
1647        }
1648    }
1649}
1650
1651// NOTE: This struct is generic over the FieldIdx for rust-analyzer usage.
1652/// Describes how the fields of a type are located in memory.
1653#[derive(#[automatically_derived]
impl<FieldIdx: ::core::cmp::PartialEq + Idx> ::core::cmp::PartialEq for
    FieldsShape<FieldIdx> {
    #[inline]
    fn eq(&self, other: &FieldsShape<FieldIdx>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (FieldsShape::Union(__self_0), FieldsShape::Union(__arg1_0))
                    => __self_0 == __arg1_0,
                (FieldsShape::Array { stride: __self_0, count: __self_1 },
                    FieldsShape::Array { stride: __arg1_0, count: __arg1_1 }) =>
                    __self_1 == __arg1_1 && __self_0 == __arg1_0,
                (FieldsShape::Arbitrary {
                    offsets: __self_0, in_memory_order: __self_1 },
                    FieldsShape::Arbitrary {
                    offsets: __arg1_0, in_memory_order: __arg1_1 }) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl<FieldIdx: ::core::cmp::Eq + Idx> ::core::cmp::Eq for
    FieldsShape<FieldIdx> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<NonZeroUsize>;
        let _: ::core::cmp::AssertParamIsEq<Size>;
        let _: ::core::cmp::AssertParamIsEq<u64>;
        let _: ::core::cmp::AssertParamIsEq<IndexVec<FieldIdx, Size>>;
        let _: ::core::cmp::AssertParamIsEq<IndexVec<u32, FieldIdx>>;
    }
}Eq, #[automatically_derived]
impl<FieldIdx: ::core::hash::Hash + Idx> ::core::hash::Hash for
    FieldsShape<FieldIdx> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            FieldsShape::Union(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            FieldsShape::Array { stride: __self_0, count: __self_1 } => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state)
            }
            FieldsShape::Arbitrary {
                offsets: __self_0, in_memory_order: __self_1 } => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state)
            }
            _ => {}
        }
    }
}Hash, #[automatically_derived]
impl<FieldIdx: ::core::clone::Clone + Idx> ::core::clone::Clone for
    FieldsShape<FieldIdx> {
    #[inline]
    fn clone(&self) -> FieldsShape<FieldIdx> {
        match self {
            FieldsShape::Primitive => FieldsShape::Primitive,
            FieldsShape::Union(__self_0) =>
                FieldsShape::Union(::core::clone::Clone::clone(__self_0)),
            FieldsShape::Array { stride: __self_0, count: __self_1 } =>
                FieldsShape::Array {
                    stride: ::core::clone::Clone::clone(__self_0),
                    count: ::core::clone::Clone::clone(__self_1),
                },
            FieldsShape::Arbitrary {
                offsets: __self_0, in_memory_order: __self_1 } =>
                FieldsShape::Arbitrary {
                    offsets: ::core::clone::Clone::clone(__self_0),
                    in_memory_order: ::core::clone::Clone::clone(__self_1),
                },
        }
    }
}Clone, #[automatically_derived]
impl<FieldIdx: ::core::fmt::Debug + Idx> ::core::fmt::Debug for
    FieldsShape<FieldIdx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            FieldsShape::Primitive =>
                ::core::fmt::Formatter::write_str(f, "Primitive"),
            FieldsShape::Union(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Union",
                    &__self_0),
            FieldsShape::Array { stride: __self_0, count: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f, "Array",
                    "stride", __self_0, "count", &__self_1),
            FieldsShape::Arbitrary {
                offsets: __self_0, in_memory_order: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "Arbitrary", "offsets", __self_0, "in_memory_order",
                    &__self_1),
        }
    }
}Debug)]
1654#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl<FieldIdx: Idx, __CTX>
            ::rustc_data_structures::stable_hasher::HashStable<__CTX> for
            FieldsShape<FieldIdx> where
            __CTX: ::rustc_span::HashStableContext,
            FieldIdx: ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    FieldsShape::Primitive => {}
                    FieldsShape::Union(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    FieldsShape::Array {
                        stride: ref __binding_0, count: ref __binding_1 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                    }
                    FieldsShape::Arbitrary {
                        offsets: ref __binding_0, in_memory_order: ref __binding_1 }
                        => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic))]
1655pub enum FieldsShape<FieldIdx: Idx> {
1656    /// Scalar primitives and `!`, which never have fields.
1657    Primitive,
1658
1659    /// All fields start at no offset. The `usize` is the field count.
1660    Union(NonZeroUsize),
1661
1662    /// Array/vector-like placement, with all fields of identical types.
1663    Array { stride: Size, count: u64 },
1664
1665    /// Struct-like placement, with precomputed offsets.
1666    ///
1667    /// Fields are guaranteed to not overlap, but note that gaps
1668    /// before, between and after all the fields are NOT always
1669    /// padding, and as such their contents may not be discarded.
1670    /// For example, enum variants leave a gap at the start,
1671    /// where the discriminant field in the enum layout goes.
1672    Arbitrary {
1673        /// Offsets for the first byte of each field,
1674        /// ordered to match the source definition order.
1675        /// This vector does not go in increasing order.
1676        // FIXME(eddyb) use small vector optimization for the common case.
1677        offsets: IndexVec<FieldIdx, Size>,
1678
1679        /// Maps memory order field indices to source order indices,
1680        /// depending on how the fields were reordered (if at all).
1681        /// This is a permutation, with both the source order and the
1682        /// memory order using the same (0..n) index ranges.
1683        ///
1684        // FIXME(eddyb) build a better abstraction for permutations, if possible.
1685        // FIXME(camlorn) also consider small vector optimization here.
1686        in_memory_order: IndexVec<u32, FieldIdx>,
1687    },
1688}
1689
1690impl<FieldIdx: Idx> FieldsShape<FieldIdx> {
1691    #[inline]
1692    pub fn count(&self) -> usize {
1693        match *self {
1694            FieldsShape::Primitive => 0,
1695            FieldsShape::Union(count) => count.get(),
1696            FieldsShape::Array { count, .. } => count.try_into().unwrap(),
1697            FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(),
1698        }
1699    }
1700
1701    #[inline]
1702    pub fn offset(&self, i: usize) -> Size {
1703        match *self {
1704            FieldsShape::Primitive => {
1705                {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("FieldsShape::offset: `Primitive`s have no fields")));
}unreachable!("FieldsShape::offset: `Primitive`s have no fields")
1706            }
1707            FieldsShape::Union(count) => {
1708                if !(i < count.get()) {
    {
        ::core::panicking::panic_fmt(format_args!("tried to access field {0} of union with {1} fields",
                i, count));
    }
};assert!(i < count.get(), "tried to access field {i} of union with {count} fields");
1709                Size::ZERO
1710            }
1711            FieldsShape::Array { stride, count } => {
1712                let i = u64::try_from(i).unwrap();
1713                if !(i < count) {
    {
        ::core::panicking::panic_fmt(format_args!("tried to access field {0} of array with {1} fields",
                i, count));
    }
};assert!(i < count, "tried to access field {i} of array with {count} fields");
1714                stride * i
1715            }
1716            FieldsShape::Arbitrary { ref offsets, .. } => offsets[FieldIdx::new(i)],
1717        }
1718    }
1719
1720    /// Gets source indices of the fields by increasing offsets.
1721    #[inline]
1722    pub fn index_by_increasing_offset(&self) -> impl ExactSizeIterator<Item = usize> {
1723        // Primitives don't really have fields in the way that structs do,
1724        // but having this return an empty iterator for them is unhelpful
1725        // since that makes them look kinda like ZSTs, which they're not.
1726        let pseudofield_count = if let FieldsShape::Primitive = self { 1 } else { self.count() };
1727
1728        (0..pseudofield_count).map(move |i| match self {
1729            FieldsShape::Primitive | FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
1730            FieldsShape::Arbitrary { in_memory_order, .. } => in_memory_order[i as u32].index(),
1731        })
1732    }
1733}
1734
1735/// An identifier that specifies the address space that some operation
1736/// should operate on. Special address spaces have an effect on code generation,
1737/// depending on the target and the address spaces it implements.
1738#[derive(#[automatically_derived]
impl ::core::marker::Copy for AddressSpace { }Copy, #[automatically_derived]
impl ::core::clone::Clone for AddressSpace {
    #[inline]
    fn clone(&self) -> AddressSpace {
        let _: ::core::clone::AssertParamIsClone<u32>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for AddressSpace {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f, "AddressSpace",
            &&self.0)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for AddressSpace {
    #[inline]
    fn eq(&self, other: &AddressSpace) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for AddressSpace {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<u32>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for AddressSpace {
    #[inline]
    fn partial_cmp(&self, other: &AddressSpace)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0)
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for AddressSpace {
    #[inline]
    fn cmp(&self, other: &AddressSpace) -> ::core::cmp::Ordering {
        ::core::cmp::Ord::cmp(&self.0, &other.0)
    }
}Ord, #[automatically_derived]
impl ::core::hash::Hash for AddressSpace {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.0, state)
    }
}Hash)]
1739#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for AddressSpace where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    AddressSpace(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic))]
1740pub struct AddressSpace(pub u32);
1741
1742impl AddressSpace {
1743    /// LLVM's `0` address space.
1744    pub const ZERO: Self = AddressSpace(0);
1745}
1746
1747/// How many scalable vectors are in a `BackendRepr::ScalableVector`?
1748#[derive(#[automatically_derived]
impl ::core::clone::Clone for NumScalableVectors {
    #[inline]
    fn clone(&self) -> NumScalableVectors {
        let _: ::core::clone::AssertParamIsClone<u8>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for NumScalableVectors { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for NumScalableVectors {
    #[inline]
    fn eq(&self, other: &NumScalableVectors) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for NumScalableVectors {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<u8>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for NumScalableVectors {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.0, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for NumScalableVectors {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f,
            "NumScalableVectors", &&self.0)
    }
}Debug)]
1749#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for NumScalableVectors where
            __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    NumScalableVectors(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic))]
1750pub struct NumScalableVectors(pub u8);
1751
1752impl NumScalableVectors {
1753    /// Returns a `NumScalableVector` for a non-tuple scalable vector (e.g. a single vector).
1754    pub fn for_non_tuple() -> Self {
1755        NumScalableVectors(1)
1756    }
1757
1758    // Returns `NumScalableVectors` for values of two through eight, which are a valid number of
1759    // fields for a tuple of scalable vectors to have. `1` is a valid value of `NumScalableVectors`
1760    // but not for a tuple which would have a field count.
1761    pub fn from_field_count(count: usize) -> Option<Self> {
1762        match count {
1763            2..8 => Some(NumScalableVectors(count as u8)),
1764            _ => None,
1765        }
1766    }
1767}
1768
1769/// The way we represent values to the backend
1770///
1771/// Previously this was conflated with the "ABI" a type is given, as in the platform-specific ABI.
1772/// In reality, this implies little about that, but is mostly used to describe the syntactic form
1773/// emitted for the backend, as most backends handle SSA values and blobs of memory differently.
1774/// The psABI may need consideration in doing so, but this enum does not constitute a promise for
1775/// how the value will be lowered to the calling convention, in itself.
1776///
1777/// Generally, a codegen backend will prefer to handle smaller values as a scalar or short vector,
1778/// and larger values will usually prefer to be represented as memory.
1779#[derive(#[automatically_derived]
impl ::core::clone::Clone for BackendRepr {
    #[inline]
    fn clone(&self) -> BackendRepr {
        let _: ::core::clone::AssertParamIsClone<Scalar>;
        let _: ::core::clone::AssertParamIsClone<u64>;
        let _: ::core::clone::AssertParamIsClone<NumScalableVectors>;
        let _: ::core::clone::AssertParamIsClone<bool>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for BackendRepr { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for BackendRepr {
    #[inline]
    fn eq(&self, other: &BackendRepr) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (BackendRepr::Scalar(__self_0), BackendRepr::Scalar(__arg1_0))
                    => __self_0 == __arg1_0,
                (BackendRepr::ScalarPair(__self_0, __self_1),
                    BackendRepr::ScalarPair(__arg1_0, __arg1_1)) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                (BackendRepr::SimdScalableVector {
                    element: __self_0,
                    count: __self_1,
                    number_of_vectors: __self_2 },
                    BackendRepr::SimdScalableVector {
                    element: __arg1_0,
                    count: __arg1_1,
                    number_of_vectors: __arg1_2 }) =>
                    __self_1 == __arg1_1 && __self_0 == __arg1_0 &&
                        __self_2 == __arg1_2,
                (BackendRepr::SimdVector { element: __self_0, count: __self_1
                    }, BackendRepr::SimdVector {
                    element: __arg1_0, count: __arg1_1 }) =>
                    __self_1 == __arg1_1 && __self_0 == __arg1_0,
                (BackendRepr::Memory { sized: __self_0 },
                    BackendRepr::Memory { sized: __arg1_0 }) =>
                    __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for BackendRepr {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Scalar>;
        let _: ::core::cmp::AssertParamIsEq<u64>;
        let _: ::core::cmp::AssertParamIsEq<NumScalableVectors>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for BackendRepr {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            BackendRepr::Scalar(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            BackendRepr::ScalarPair(__self_0, __self_1) => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state)
            }
            BackendRepr::SimdScalableVector {
                element: __self_0,
                count: __self_1,
                number_of_vectors: __self_2 } => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state);
                ::core::hash::Hash::hash(__self_2, state)
            }
            BackendRepr::SimdVector { element: __self_0, count: __self_1 } =>
                {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state)
            }
            BackendRepr::Memory { sized: __self_0 } =>
                ::core::hash::Hash::hash(__self_0, state),
        }
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for BackendRepr {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            BackendRepr::Scalar(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Scalar",
                    &__self_0),
            BackendRepr::ScalarPair(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f,
                    "ScalarPair", __self_0, &__self_1),
            BackendRepr::SimdScalableVector {
                element: __self_0,
                count: __self_1,
                number_of_vectors: __self_2 } =>
                ::core::fmt::Formatter::debug_struct_field3_finish(f,
                    "SimdScalableVector", "element", __self_0, "count",
                    __self_1, "number_of_vectors", &__self_2),
            BackendRepr::SimdVector { element: __self_0, count: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "SimdVector", "element", __self_0, "count", &__self_1),
            BackendRepr::Memory { sized: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "Memory", "sized", &__self_0),
        }
    }
}Debug)]
1780#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for BackendRepr where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    BackendRepr::Scalar(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    BackendRepr::ScalarPair(ref __binding_0, ref __binding_1) =>
                        {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                    }
                    BackendRepr::SimdScalableVector {
                        element: ref __binding_0,
                        count: ref __binding_1,
                        number_of_vectors: ref __binding_2 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                        { __binding_2.hash_stable(__hcx, __hasher); }
                    }
                    BackendRepr::SimdVector {
                        element: ref __binding_0, count: ref __binding_1 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                    }
                    BackendRepr::Memory { sized: ref __binding_0 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic))]
1781pub enum BackendRepr {
1782    Scalar(Scalar),
1783    ScalarPair(Scalar, Scalar),
1784    SimdScalableVector {
1785        element: Scalar,
1786        count: u64,
1787        number_of_vectors: NumScalableVectors,
1788    },
1789    SimdVector {
1790        element: Scalar,
1791        count: u64,
1792    },
1793    // FIXME: I sometimes use memory, sometimes use an IR aggregate!
1794    Memory {
1795        /// If true, the size is exact, otherwise it's only a lower bound.
1796        sized: bool,
1797    },
1798}
1799
1800impl BackendRepr {
1801    /// Returns `true` if the layout corresponds to an unsized type.
1802    #[inline]
1803    pub fn is_unsized(&self) -> bool {
1804        match *self {
1805            BackendRepr::Scalar(_)
1806            | BackendRepr::ScalarPair(..)
1807            // FIXME(rustc_scalable_vector): Scalable vectors are `Sized` while the
1808            // `sized_hierarchy` feature is not yet fully implemented. After `sized_hierarchy` is
1809            // fully implemented, scalable vectors will remain `Sized`, they just won't be
1810            // `const Sized` - whether `is_unsized` continues to return `false` at that point will
1811            // need to be revisited and will depend on what `is_unsized` is used for.
1812            | BackendRepr::SimdScalableVector { .. }
1813            | BackendRepr::SimdVector { .. } => false,
1814            BackendRepr::Memory { sized } => !sized,
1815        }
1816    }
1817
1818    #[inline]
1819    pub fn is_sized(&self) -> bool {
1820        !self.is_unsized()
1821    }
1822
1823    /// Returns `true` if this is a single signed integer scalar.
1824    /// Sanity check: panics if this is not a scalar type (see PR #70189).
1825    #[inline]
1826    pub fn is_signed(&self) -> bool {
1827        match self {
1828            BackendRepr::Scalar(scal) => scal.is_signed(),
1829            _ => {
    ::core::panicking::panic_fmt(format_args!("`is_signed` on non-scalar ABI {0:?}",
            self));
}panic!("`is_signed` on non-scalar ABI {self:?}"),
1830        }
1831    }
1832
1833    /// Returns `true` if this is a scalar type
1834    #[inline]
1835    pub fn is_scalar(&self) -> bool {
1836        #[allow(non_exhaustive_omitted_patterns)] match *self {
    BackendRepr::Scalar(_) => true,
    _ => false,
}matches!(*self, BackendRepr::Scalar(_))
1837    }
1838
1839    /// Returns `true` if this is a bool
1840    #[inline]
1841    pub fn is_bool(&self) -> bool {
1842        #[allow(non_exhaustive_omitted_patterns)] match *self {
    BackendRepr::Scalar(s) if s.is_bool() => true,
    _ => false,
}matches!(*self, BackendRepr::Scalar(s) if s.is_bool())
1843    }
1844
1845    /// The psABI alignment for a `Scalar` or `ScalarPair`
1846    ///
1847    /// `None` for other variants.
1848    pub fn scalar_align<C: HasDataLayout>(&self, cx: &C) -> Option<Align> {
1849        match *self {
1850            BackendRepr::Scalar(s) => Some(s.align(cx).abi),
1851            BackendRepr::ScalarPair(s1, s2) => Some(s1.align(cx).max(s2.align(cx)).abi),
1852            // The align of a Vector can vary in surprising ways
1853            BackendRepr::SimdVector { .. }
1854            | BackendRepr::Memory { .. }
1855            | BackendRepr::SimdScalableVector { .. } => None,
1856        }
1857    }
1858
1859    /// The psABI size for a `Scalar` or `ScalarPair`
1860    ///
1861    /// `None` for other variants
1862    pub fn scalar_size<C: HasDataLayout>(&self, cx: &C) -> Option<Size> {
1863        match *self {
1864            // No padding in scalars.
1865            BackendRepr::Scalar(s) => Some(s.size(cx)),
1866            // May have some padding between the pair.
1867            BackendRepr::ScalarPair(s1, s2) => {
1868                let field2_offset = s1.size(cx).align_to(s2.align(cx).abi);
1869                let size = (field2_offset + s2.size(cx)).align_to(
1870                    self.scalar_align(cx)
1871                        // We absolutely must have an answer here or everything is FUBAR.
1872                        .unwrap(),
1873                );
1874                Some(size)
1875            }
1876            // The size of a Vector can vary in surprising ways
1877            BackendRepr::SimdVector { .. }
1878            | BackendRepr::Memory { .. }
1879            | BackendRepr::SimdScalableVector { .. } => None,
1880        }
1881    }
1882
1883    /// Discard validity range information and allow undef.
1884    pub fn to_union(&self) -> Self {
1885        match *self {
1886            BackendRepr::Scalar(s) => BackendRepr::Scalar(s.to_union()),
1887            BackendRepr::ScalarPair(s1, s2) => {
1888                BackendRepr::ScalarPair(s1.to_union(), s2.to_union())
1889            }
1890            BackendRepr::SimdVector { element, count } => {
1891                BackendRepr::SimdVector { element: element.to_union(), count }
1892            }
1893            BackendRepr::Memory { .. } => BackendRepr::Memory { sized: true },
1894            BackendRepr::SimdScalableVector { element, count, number_of_vectors } => {
1895                BackendRepr::SimdScalableVector {
1896                    element: element.to_union(),
1897                    count,
1898                    number_of_vectors,
1899                }
1900            }
1901        }
1902    }
1903
1904    pub fn eq_up_to_validity(&self, other: &Self) -> bool {
1905        match (self, other) {
1906            // Scalar, Vector, ScalarPair have `Scalar` in them where we ignore validity ranges.
1907            // We do *not* ignore the sign since it matters for some ABIs (e.g. s390x).
1908            (BackendRepr::Scalar(l), BackendRepr::Scalar(r)) => l.primitive() == r.primitive(),
1909            (
1910                BackendRepr::SimdVector { element: element_l, count: count_l },
1911                BackendRepr::SimdVector { element: element_r, count: count_r },
1912            ) => element_l.primitive() == element_r.primitive() && count_l == count_r,
1913            (BackendRepr::ScalarPair(l1, l2), BackendRepr::ScalarPair(r1, r2)) => {
1914                l1.primitive() == r1.primitive() && l2.primitive() == r2.primitive()
1915            }
1916            // Everything else must be strictly identical.
1917            _ => self == other,
1918        }
1919    }
1920}
1921
1922// NOTE: This struct is generic over the FieldIdx and VariantIdx for rust-analyzer usage.
1923#[derive(#[automatically_derived]
impl<FieldIdx: ::core::cmp::PartialEq + Idx,
    VariantIdx: ::core::cmp::PartialEq + Idx> ::core::cmp::PartialEq for
    Variants<FieldIdx, VariantIdx> {
    #[inline]
    fn eq(&self, other: &Variants<FieldIdx, VariantIdx>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (Variants::Single { index: __self_0 }, Variants::Single {
                    index: __arg1_0 }) => __self_0 == __arg1_0,
                (Variants::Multiple {
                    tag: __self_0,
                    tag_encoding: __self_1,
                    tag_field: __self_2,
                    variants: __self_3 }, Variants::Multiple {
                    tag: __arg1_0,
                    tag_encoding: __arg1_1,
                    tag_field: __arg1_2,
                    variants: __arg1_3 }) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1 &&
                            __self_2 == __arg1_2 && __self_3 == __arg1_3,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl<FieldIdx: ::core::cmp::Eq + Idx, VariantIdx: ::core::cmp::Eq + Idx>
    ::core::cmp::Eq for Variants<FieldIdx, VariantIdx> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<VariantIdx>;
        let _: ::core::cmp::AssertParamIsEq<Scalar>;
        let _: ::core::cmp::AssertParamIsEq<TagEncoding<VariantIdx>>;
        let _: ::core::cmp::AssertParamIsEq<FieldIdx>;
        let _:
                ::core::cmp::AssertParamIsEq<IndexVec<VariantIdx,
                LayoutData<FieldIdx, VariantIdx>>>;
    }
}Eq, #[automatically_derived]
impl<FieldIdx: ::core::hash::Hash + Idx, VariantIdx: ::core::hash::Hash + Idx>
    ::core::hash::Hash for Variants<FieldIdx, VariantIdx> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            Variants::Single { index: __self_0 } =>
                ::core::hash::Hash::hash(__self_0, state),
            Variants::Multiple {
                tag: __self_0,
                tag_encoding: __self_1,
                tag_field: __self_2,
                variants: __self_3 } => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state);
                ::core::hash::Hash::hash(__self_2, state);
                ::core::hash::Hash::hash(__self_3, state)
            }
            _ => {}
        }
    }
}Hash, #[automatically_derived]
impl<FieldIdx: ::core::clone::Clone + Idx, VariantIdx: ::core::clone::Clone +
    Idx> ::core::clone::Clone for Variants<FieldIdx, VariantIdx> {
    #[inline]
    fn clone(&self) -> Variants<FieldIdx, VariantIdx> {
        match self {
            Variants::Empty => Variants::Empty,
            Variants::Single { index: __self_0 } =>
                Variants::Single {
                    index: ::core::clone::Clone::clone(__self_0),
                },
            Variants::Multiple {
                tag: __self_0,
                tag_encoding: __self_1,
                tag_field: __self_2,
                variants: __self_3 } =>
                Variants::Multiple {
                    tag: ::core::clone::Clone::clone(__self_0),
                    tag_encoding: ::core::clone::Clone::clone(__self_1),
                    tag_field: ::core::clone::Clone::clone(__self_2),
                    variants: ::core::clone::Clone::clone(__self_3),
                },
        }
    }
}Clone, #[automatically_derived]
impl<FieldIdx: ::core::fmt::Debug + Idx, VariantIdx: ::core::fmt::Debug + Idx>
    ::core::fmt::Debug for Variants<FieldIdx, VariantIdx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Variants::Empty => ::core::fmt::Formatter::write_str(f, "Empty"),
            Variants::Single { index: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "Single", "index", &__self_0),
            Variants::Multiple {
                tag: __self_0,
                tag_encoding: __self_1,
                tag_field: __self_2,
                variants: __self_3 } =>
                ::core::fmt::Formatter::debug_struct_field4_finish(f,
                    "Multiple", "tag", __self_0, "tag_encoding", __self_1,
                    "tag_field", __self_2, "variants", &__self_3),
        }
    }
}Debug)]
1924#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl<FieldIdx: Idx, VariantIdx: Idx, __CTX>
            ::rustc_data_structures::stable_hasher::HashStable<__CTX> for
            Variants<FieldIdx, VariantIdx> where
            __CTX: ::rustc_span::HashStableContext,
            VariantIdx: ::rustc_data_structures::stable_hasher::HashStable<__CTX>,
            FieldIdx: ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    Variants::Empty => {}
                    Variants::Single { index: ref __binding_0 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    Variants::Multiple {
                        tag: ref __binding_0,
                        tag_encoding: ref __binding_1,
                        tag_field: ref __binding_2,
                        variants: ref __binding_3 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                        { __binding_2.hash_stable(__hcx, __hasher); }
                        { __binding_3.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic))]
1925pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
1926    /// A type with no valid variants. Must be uninhabited.
1927    Empty,
1928
1929    /// Single enum variants, structs/tuples, unions, and all non-ADTs.
1930    Single {
1931        /// Always `0` for types that cannot have multiple variants.
1932        index: VariantIdx,
1933    },
1934
1935    /// Enum-likes with more than one variant: each variant comes with
1936    /// a *discriminant* (usually the same as the variant index but the user can
1937    /// assign explicit discriminant values). That discriminant is encoded
1938    /// as a *tag* on the machine. The layout of each variant is
1939    /// a struct, and they all have space reserved for the tag.
1940    /// For enums, the tag is the sole field of the layout.
1941    Multiple {
1942        tag: Scalar,
1943        tag_encoding: TagEncoding<VariantIdx>,
1944        tag_field: FieldIdx,
1945        variants: IndexVec<VariantIdx, LayoutData<FieldIdx, VariantIdx>>,
1946    },
1947}
1948
1949// NOTE: This struct is generic over the VariantIdx for rust-analyzer usage.
1950#[derive(#[automatically_derived]
impl<VariantIdx: ::core::cmp::PartialEq + Idx> ::core::cmp::PartialEq for
    TagEncoding<VariantIdx> {
    #[inline]
    fn eq(&self, other: &TagEncoding<VariantIdx>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (TagEncoding::Niche {
                    untagged_variant: __self_0,
                    niche_variants: __self_1,
                    niche_start: __self_2 }, TagEncoding::Niche {
                    untagged_variant: __arg1_0,
                    niche_variants: __arg1_1,
                    niche_start: __arg1_2 }) =>
                    __self_2 == __arg1_2 && __self_0 == __arg1_0 &&
                        __self_1 == __arg1_1,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl<VariantIdx: ::core::cmp::Eq + Idx> ::core::cmp::Eq for
    TagEncoding<VariantIdx> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<VariantIdx>;
        let _: ::core::cmp::AssertParamIsEq<RangeInclusive<VariantIdx>>;
        let _: ::core::cmp::AssertParamIsEq<u128>;
    }
}Eq, #[automatically_derived]
impl<VariantIdx: ::core::hash::Hash + Idx> ::core::hash::Hash for
    TagEncoding<VariantIdx> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            TagEncoding::Niche {
                untagged_variant: __self_0,
                niche_variants: __self_1,
                niche_start: __self_2 } => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state);
                ::core::hash::Hash::hash(__self_2, state)
            }
            _ => {}
        }
    }
}Hash, #[automatically_derived]
impl<VariantIdx: ::core::clone::Clone + Idx> ::core::clone::Clone for
    TagEncoding<VariantIdx> {
    #[inline]
    fn clone(&self) -> TagEncoding<VariantIdx> {
        match self {
            TagEncoding::Direct => TagEncoding::Direct,
            TagEncoding::Niche {
                untagged_variant: __self_0,
                niche_variants: __self_1,
                niche_start: __self_2 } =>
                TagEncoding::Niche {
                    untagged_variant: ::core::clone::Clone::clone(__self_0),
                    niche_variants: ::core::clone::Clone::clone(__self_1),
                    niche_start: ::core::clone::Clone::clone(__self_2),
                },
        }
    }
}Clone, #[automatically_derived]
impl<VariantIdx: ::core::fmt::Debug + Idx> ::core::fmt::Debug for
    TagEncoding<VariantIdx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            TagEncoding::Direct =>
                ::core::fmt::Formatter::write_str(f, "Direct"),
            TagEncoding::Niche {
                untagged_variant: __self_0,
                niche_variants: __self_1,
                niche_start: __self_2 } =>
                ::core::fmt::Formatter::debug_struct_field3_finish(f, "Niche",
                    "untagged_variant", __self_0, "niche_variants", __self_1,
                    "niche_start", &__self_2),
        }
    }
}Debug)]
1951#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl<VariantIdx: Idx, __CTX>
            ::rustc_data_structures::stable_hasher::HashStable<__CTX> for
            TagEncoding<VariantIdx> where
            __CTX: ::rustc_span::HashStableContext,
            VariantIdx: ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    TagEncoding::Direct => {}
                    TagEncoding::Niche {
                        untagged_variant: ref __binding_0,
                        niche_variants: ref __binding_1,
                        niche_start: ref __binding_2 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                        { __binding_2.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic))]
1952pub enum TagEncoding<VariantIdx: Idx> {
1953    /// The tag directly stores the discriminant, but possibly with a smaller layout
1954    /// (so converting the tag to the discriminant can require sign extension).
1955    Direct,
1956
1957    /// Niche (values invalid for a type) encoding the discriminant.
1958    /// Note that for this encoding, the discriminant and variant index of each variant coincide!
1959    /// This invariant is codified as part of [`layout_sanity_check`](../rustc_ty_utils/layout/invariant/fn.layout_sanity_check.html).
1960    ///
1961    /// The variant `untagged_variant` contains a niche at an arbitrary
1962    /// offset (field [`Variants::Multiple::tag_field`] of the enum).
1963    /// For a variant with variant index `i`, such that `i != untagged_variant`,
1964    /// the tag is set to `(i - niche_variants.start).wrapping_add(niche_start)`
1965    /// (this is wrapping arithmetic using the type of the niche field, cf. the
1966    /// [`tag_for_variant`](../rustc_const_eval/interpret/struct.InterpCx.html#method.tag_for_variant)
1967    /// query implementation).
1968    /// To recover the variant index `i` from a `tag`, the above formula has to be reversed,
1969    /// i.e. `i = tag.wrapping_sub(niche_start) + niche_variants.start`. If `i` ends up outside
1970    /// `niche_variants`, the tag must have encoded the `untagged_variant`.
1971    ///
1972    /// For example, `Option<(usize, &T)>`  is represented such that the tag for
1973    /// `None` is the null pointer in the second tuple field, and
1974    /// `Some` is the identity function (with a non-null reference)
1975    /// and has no additional tag, i.e. the reference being non-null uniquely identifies this variant.
1976    ///
1977    /// Other variants that are not `untagged_variant` and that are outside the `niche_variants`
1978    /// range cannot be represented; they must be uninhabited.
1979    /// Nonetheless, uninhabited variants can also fall into the range of `niche_variants`.
1980    Niche {
1981        untagged_variant: VariantIdx,
1982        /// This range *may* contain `untagged_variant` or uninhabited variants;
1983        /// these are then just "dead values" and not used to encode anything.
1984        niche_variants: RangeInclusive<VariantIdx>,
1985        /// This is inbounds of the type of the niche field
1986        /// (not sign-extended, i.e., all bits beyond the niche field size are 0).
1987        niche_start: u128,
1988    },
1989}
1990
1991#[derive(#[automatically_derived]
impl ::core::clone::Clone for Niche {
    #[inline]
    fn clone(&self) -> Niche {
        let _: ::core::clone::AssertParamIsClone<Size>;
        let _: ::core::clone::AssertParamIsClone<Primitive>;
        let _: ::core::clone::AssertParamIsClone<WrappingRange>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Niche { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for Niche {
    #[inline]
    fn eq(&self, other: &Niche) -> bool {
        self.offset == other.offset && self.value == other.value &&
            self.valid_range == other.valid_range
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Niche {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Size>;
        let _: ::core::cmp::AssertParamIsEq<Primitive>;
        let _: ::core::cmp::AssertParamIsEq<WrappingRange>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for Niche {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.offset, state);
        ::core::hash::Hash::hash(&self.value, state);
        ::core::hash::Hash::hash(&self.valid_range, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Niche {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f, "Niche",
            "offset", &self.offset, "value", &self.value, "valid_range",
            &&self.valid_range)
    }
}Debug)]
1992#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for Niche where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    Niche {
                        offset: ref __binding_0,
                        value: ref __binding_1,
                        valid_range: ref __binding_2 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                        { __binding_2.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic))]
1993pub struct Niche {
1994    pub offset: Size,
1995    pub value: Primitive,
1996    pub valid_range: WrappingRange,
1997}
1998
1999impl Niche {
2000    pub fn from_scalar<C: HasDataLayout>(cx: &C, offset: Size, scalar: Scalar) -> Option<Self> {
2001        let Scalar::Initialized { value, valid_range } = scalar else { return None };
2002        let niche = Niche { offset, value, valid_range };
2003        if niche.available(cx) > 0 { Some(niche) } else { None }
2004    }
2005
2006    pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
2007        let Self { value, valid_range: v, .. } = *self;
2008        let size = value.size(cx);
2009        if !(size.bits() <= 128) {
    ::core::panicking::panic("assertion failed: size.bits() <= 128")
};assert!(size.bits() <= 128);
2010        let max_value = size.unsigned_int_max();
2011
2012        // Find out how many values are outside the valid range.
2013        let niche = v.end.wrapping_add(1)..v.start;
2014        niche.end.wrapping_sub(niche.start) & max_value
2015    }
2016
2017    pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> {
2018        if !(count > 0) { ::core::panicking::panic("assertion failed: count > 0") };assert!(count > 0);
2019
2020        let Self { value, valid_range: v, .. } = *self;
2021        let size = value.size(cx);
2022        if !(size.bits() <= 128) {
    ::core::panicking::panic("assertion failed: size.bits() <= 128")
};assert!(size.bits() <= 128);
2023        let max_value = size.unsigned_int_max();
2024
2025        let niche = v.end.wrapping_add(1)..v.start;
2026        let available = niche.end.wrapping_sub(niche.start) & max_value;
2027        if count > available {
2028            return None;
2029        }
2030
2031        // Extend the range of valid values being reserved by moving either `v.start` or `v.end`
2032        // bound. Given an eventual `Option<T>`, we try to maximize the chance for `None` to occupy
2033        // the niche of zero. This is accomplished by preferring enums with 2 variants(`count==1`)
2034        // and always taking the shortest path to niche zero. Having `None` in niche zero can
2035        // enable some special optimizations.
2036        //
2037        // Bound selection criteria:
2038        // 1. Select closest to zero given wrapping semantics.
2039        // 2. Avoid moving past zero if possible.
2040        //
2041        // In practice this means that enums with `count > 1` are unlikely to claim niche zero,
2042        // since they have to fit perfectly. If niche zero is already reserved, the selection of
2043        // bounds are of little interest.
2044        let move_start = |v: WrappingRange| {
2045            let start = v.start.wrapping_sub(count) & max_value;
2046            Some((start, Scalar::Initialized { value, valid_range: v.with_start(start) }))
2047        };
2048        let move_end = |v: WrappingRange| {
2049            let start = v.end.wrapping_add(1) & max_value;
2050            let end = v.end.wrapping_add(count) & max_value;
2051            Some((start, Scalar::Initialized { value, valid_range: v.with_end(end) }))
2052        };
2053        let distance_end_zero = max_value - v.end;
2054        if v.start > v.end {
2055            // zero is unavailable because wrapping occurs
2056            move_end(v)
2057        } else if v.start <= distance_end_zero {
2058            if count <= v.start {
2059                move_start(v)
2060            } else {
2061                // moved past zero, use other bound
2062                move_end(v)
2063            }
2064        } else {
2065            let end = v.end.wrapping_add(count) & max_value;
2066            let overshot_zero = (1..=v.end).contains(&end);
2067            if overshot_zero {
2068                // moved past zero, use other bound
2069                move_start(v)
2070            } else {
2071                move_end(v)
2072            }
2073        }
2074    }
2075}
2076
2077// NOTE: This struct is generic over the FieldIdx and VariantIdx for rust-analyzer usage.
2078#[derive(#[automatically_derived]
impl<FieldIdx: ::core::cmp::PartialEq + Idx,
    VariantIdx: ::core::cmp::PartialEq + Idx> ::core::cmp::PartialEq for
    LayoutData<FieldIdx, VariantIdx> {
    #[inline]
    fn eq(&self, other: &LayoutData<FieldIdx, VariantIdx>) -> bool {
        self.uninhabited == other.uninhabited && self.fields == other.fields
                                        && self.variants == other.variants &&
                                    self.backend_repr == other.backend_repr &&
                                self.largest_niche == other.largest_niche &&
                            self.align == other.align && self.size == other.size &&
                    self.max_repr_align == other.max_repr_align &&
                self.unadjusted_abi_align == other.unadjusted_abi_align &&
            self.randomization_seed == other.randomization_seed
    }
}PartialEq, #[automatically_derived]
impl<FieldIdx: ::core::cmp::Eq + Idx, VariantIdx: ::core::cmp::Eq + Idx>
    ::core::cmp::Eq for LayoutData<FieldIdx, VariantIdx> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<FieldsShape<FieldIdx>>;
        let _: ::core::cmp::AssertParamIsEq<Variants<FieldIdx, VariantIdx>>;
        let _: ::core::cmp::AssertParamIsEq<BackendRepr>;
        let _: ::core::cmp::AssertParamIsEq<Option<Niche>>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
        let _: ::core::cmp::AssertParamIsEq<AbiAlign>;
        let _: ::core::cmp::AssertParamIsEq<Size>;
        let _: ::core::cmp::AssertParamIsEq<Option<Align>>;
        let _: ::core::cmp::AssertParamIsEq<Align>;
        let _: ::core::cmp::AssertParamIsEq<Hash64>;
    }
}Eq, #[automatically_derived]
impl<FieldIdx: ::core::hash::Hash + Idx, VariantIdx: ::core::hash::Hash + Idx>
    ::core::hash::Hash for LayoutData<FieldIdx, VariantIdx> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.fields, state);
        ::core::hash::Hash::hash(&self.variants, state);
        ::core::hash::Hash::hash(&self.backend_repr, state);
        ::core::hash::Hash::hash(&self.largest_niche, state);
        ::core::hash::Hash::hash(&self.uninhabited, state);
        ::core::hash::Hash::hash(&self.align, state);
        ::core::hash::Hash::hash(&self.size, state);
        ::core::hash::Hash::hash(&self.max_repr_align, state);
        ::core::hash::Hash::hash(&self.unadjusted_abi_align, state);
        ::core::hash::Hash::hash(&self.randomization_seed, state)
    }
}Hash, #[automatically_derived]
impl<FieldIdx: ::core::clone::Clone + Idx, VariantIdx: ::core::clone::Clone +
    Idx> ::core::clone::Clone for LayoutData<FieldIdx, VariantIdx> {
    #[inline]
    fn clone(&self) -> LayoutData<FieldIdx, VariantIdx> {
        LayoutData {
            fields: ::core::clone::Clone::clone(&self.fields),
            variants: ::core::clone::Clone::clone(&self.variants),
            backend_repr: ::core::clone::Clone::clone(&self.backend_repr),
            largest_niche: ::core::clone::Clone::clone(&self.largest_niche),
            uninhabited: ::core::clone::Clone::clone(&self.uninhabited),
            align: ::core::clone::Clone::clone(&self.align),
            size: ::core::clone::Clone::clone(&self.size),
            max_repr_align: ::core::clone::Clone::clone(&self.max_repr_align),
            unadjusted_abi_align: ::core::clone::Clone::clone(&self.unadjusted_abi_align),
            randomization_seed: ::core::clone::Clone::clone(&self.randomization_seed),
        }
    }
}Clone)]
2079#[cfg_attr(feature = "nightly", derive(const _: () =
    {
        impl<FieldIdx: Idx, VariantIdx: Idx, __CTX>
            ::rustc_data_structures::stable_hasher::HashStable<__CTX> for
            LayoutData<FieldIdx, VariantIdx> where
            __CTX: ::rustc_span::HashStableContext,
            FieldIdx: ::rustc_data_structures::stable_hasher::HashStable<__CTX>,
            VariantIdx: ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    LayoutData {
                        fields: ref __binding_0,
                        variants: ref __binding_1,
                        backend_repr: ref __binding_2,
                        largest_niche: ref __binding_3,
                        uninhabited: ref __binding_4,
                        align: ref __binding_5,
                        size: ref __binding_6,
                        max_repr_align: ref __binding_7,
                        unadjusted_abi_align: ref __binding_8,
                        randomization_seed: ref __binding_9 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                        { __binding_2.hash_stable(__hcx, __hasher); }
                        { __binding_3.hash_stable(__hcx, __hasher); }
                        { __binding_4.hash_stable(__hcx, __hasher); }
                        { __binding_5.hash_stable(__hcx, __hasher); }
                        { __binding_6.hash_stable(__hcx, __hasher); }
                        { __binding_7.hash_stable(__hcx, __hasher); }
                        { __binding_8.hash_stable(__hcx, __hasher); }
                        { __binding_9.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic))]
2080pub struct LayoutData<FieldIdx: Idx, VariantIdx: Idx> {
2081    /// Says where the fields are located within the layout.
2082    pub fields: FieldsShape<FieldIdx>,
2083
2084    /// Encodes information about multi-variant layouts.
2085    /// Even with `Multiple` variants, a layout still has its own fields! Those are then
2086    /// shared between all variants. One of them will be the discriminant,
2087    /// but e.g. coroutines can have more.
2088    ///
2089    /// To access all fields of this layout, both `fields` and the fields of the active variant
2090    /// must be taken into account.
2091    pub variants: Variants<FieldIdx, VariantIdx>,
2092
2093    /// The `backend_repr` defines how this data will be represented to the codegen backend,
2094    /// and encodes value restrictions via `valid_range`.
2095    ///
2096    /// Note that this is entirely orthogonal to the recursive structure defined by
2097    /// `variants` and `fields`; for example, `ManuallyDrop<Result<isize, isize>>` has
2098    /// `IrForm::ScalarPair`! So, even with non-`Memory` `backend_repr`, `fields` and `variants`
2099    /// have to be taken into account to find all fields of this layout.
2100    pub backend_repr: BackendRepr,
2101
2102    /// The leaf scalar with the largest number of invalid values
2103    /// (i.e. outside of its `valid_range`), if it exists.
2104    pub largest_niche: Option<Niche>,
2105    /// Is this type known to be uninhabted?
2106    ///
2107    /// This is separate from BackendRepr because uninhabited return types can affect ABI,
2108    /// especially in the case of by-pointer struct returns, which allocate stack even when unused.
2109    pub uninhabited: bool,
2110
2111    pub align: AbiAlign,
2112    pub size: Size,
2113
2114    /// The largest alignment explicitly requested with `repr(align)` on this type or any field.
2115    /// Only used on i686-windows, where the argument passing ABI is different when alignment is
2116    /// requested, even if the requested alignment is equal to the natural alignment.
2117    pub max_repr_align: Option<Align>,
2118
2119    /// The alignment the type would have, ignoring any `repr(align)` but including `repr(packed)`.
2120    /// Only used on aarch64-linux, where the argument passing ABI ignores the requested alignment
2121    /// in some cases.
2122    pub unadjusted_abi_align: Align,
2123
2124    /// The randomization seed based on this type's own repr and its fields.
2125    ///
2126    /// Since randomization is toggled on a per-crate basis even crates that do not have randomization
2127    /// enabled should still calculate a seed so that downstream uses can use it to distinguish different
2128    /// types.
2129    ///
2130    /// For every T and U for which we do not guarantee that a repr(Rust) `Foo<T>` can be coerced or
2131    /// transmuted to `Foo<U>` we aim to create probalistically distinct seeds so that Foo can choose
2132    /// to reorder its fields based on that information. The current implementation is a conservative
2133    /// approximation of this goal.
2134    pub randomization_seed: Hash64,
2135}
2136
2137impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
2138    /// Returns `true` if this is an aggregate type (including a ScalarPair!)
2139    pub fn is_aggregate(&self) -> bool {
2140        match self.backend_repr {
2141            BackendRepr::Scalar(_)
2142            | BackendRepr::SimdVector { .. }
2143            | BackendRepr::SimdScalableVector { .. } => false,
2144            BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => true,
2145        }
2146    }
2147
2148    /// Returns `true` if this is an uninhabited type
2149    pub fn is_uninhabited(&self) -> bool {
2150        self.uninhabited
2151    }
2152}
2153
2154impl<FieldIdx: Idx, VariantIdx: Idx> fmt::Debug for LayoutData<FieldIdx, VariantIdx>
2155where
2156    FieldsShape<FieldIdx>: fmt::Debug,
2157    Variants<FieldIdx, VariantIdx>: fmt::Debug,
2158{
2159    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2160        // This is how `Layout` used to print before it become
2161        // `Interned<LayoutData>`. We print it like this to avoid having to update
2162        // expected output in a lot of tests.
2163        let LayoutData {
2164            size,
2165            align,
2166            backend_repr,
2167            fields,
2168            largest_niche,
2169            uninhabited,
2170            variants,
2171            max_repr_align,
2172            unadjusted_abi_align,
2173            randomization_seed,
2174        } = self;
2175        f.debug_struct("Layout")
2176            .field("size", size)
2177            .field("align", align)
2178            .field("backend_repr", backend_repr)
2179            .field("fields", fields)
2180            .field("largest_niche", largest_niche)
2181            .field("uninhabited", uninhabited)
2182            .field("variants", variants)
2183            .field("max_repr_align", max_repr_align)
2184            .field("unadjusted_abi_align", unadjusted_abi_align)
2185            .field("randomization_seed", randomization_seed)
2186            .finish()
2187    }
2188}
2189
2190#[derive(#[automatically_derived]
impl ::core::marker::Copy for PointerKind { }Copy, #[automatically_derived]
impl ::core::clone::Clone for PointerKind {
    #[inline]
    fn clone(&self) -> PointerKind {
        let _: ::core::clone::AssertParamIsClone<bool>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for PointerKind {
    #[inline]
    fn eq(&self, other: &PointerKind) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (PointerKind::SharedRef { frozen: __self_0 },
                    PointerKind::SharedRef { frozen: __arg1_0 }) =>
                    __self_0 == __arg1_0,
                (PointerKind::MutableRef { unpin: __self_0 },
                    PointerKind::MutableRef { unpin: __arg1_0 }) =>
                    __self_0 == __arg1_0,
                (PointerKind::Box { unpin: __self_0, global: __self_1 },
                    PointerKind::Box { unpin: __arg1_0, global: __arg1_1 }) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for PointerKind {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, #[automatically_derived]
impl ::core::fmt::Debug for PointerKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            PointerKind::SharedRef { frozen: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "SharedRef", "frozen", &__self_0),
            PointerKind::MutableRef { unpin: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "MutableRef", "unpin", &__self_0),
            PointerKind::Box { unpin: __self_0, global: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f, "Box",
                    "unpin", __self_0, "global", &__self_1),
        }
    }
}Debug)]
2191pub enum PointerKind {
2192    /// Shared reference. `frozen` indicates the absence of any `UnsafeCell`.
2193    SharedRef { frozen: bool },
2194    /// Mutable reference. `unpin` indicates the absence of any pinned data.
2195    MutableRef { unpin: bool },
2196    /// Box. `unpin` indicates the absence of any pinned data. `global` indicates whether this box
2197    /// uses the global allocator or a custom one.
2198    Box { unpin: bool, global: bool },
2199}
2200
2201/// Encodes extra information we have about a pointer.
2202///
2203/// Note that this information is advisory only, and backends are free to ignore it:
2204/// if the information is wrong, that can cause UB, but if the information is absent,
2205/// that must always be okay.
2206#[derive(#[automatically_derived]
impl ::core::marker::Copy for PointeeInfo { }Copy, #[automatically_derived]
impl ::core::clone::Clone for PointeeInfo {
    #[inline]
    fn clone(&self) -> PointeeInfo {
        let _: ::core::clone::AssertParamIsClone<Option<PointerKind>>;
        let _: ::core::clone::AssertParamIsClone<Size>;
        let _: ::core::clone::AssertParamIsClone<Align>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for PointeeInfo {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f, "PointeeInfo",
            "safe", &self.safe, "size", &self.size, "align", &&self.align)
    }
}Debug)]
2207pub struct PointeeInfo {
2208    /// If this is `None`, then this is a raw pointer.
2209    pub safe: Option<PointerKind>,
2210    /// If `size` is not zero, then the pointer is either null or dereferenceable for this many bytes
2211    /// (independent of `safe`).
2212    ///
2213    /// On a function argument, "dereferenceable" here means "dereferenceable for the entire duration
2214    /// of this function call", i.e. it is UB for the memory that this pointer points to be freed
2215    /// while this function is still running.
2216    pub size: Size,
2217    /// The pointer is guaranteed to be aligned this much (independent of `safe`).
2218    pub align: Align,
2219}
2220
2221impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
2222    /// Returns `true` if the layout corresponds to an unsized type.
2223    #[inline]
2224    pub fn is_unsized(&self) -> bool {
2225        self.backend_repr.is_unsized()
2226    }
2227
2228    #[inline]
2229    pub fn is_sized(&self) -> bool {
2230        self.backend_repr.is_sized()
2231    }
2232
2233    /// Returns `true` if the type is sized and a 1-ZST (meaning it has size 0 and alignment 1).
2234    pub fn is_1zst(&self) -> bool {
2235        self.is_sized() && self.size.bytes() == 0 && self.align.bytes() == 1
2236    }
2237
2238    /// Returns `true` if the size of the type is only known at runtime.
2239    pub fn is_scalable_vector(&self) -> bool {
2240        #[allow(non_exhaustive_omitted_patterns)] match self.backend_repr {
    BackendRepr::SimdScalableVector { .. } => true,
    _ => false,
}matches!(self.backend_repr, BackendRepr::SimdScalableVector { .. })
2241    }
2242
2243    /// Returns the elements count of a scalable vector.
2244    pub fn scalable_vector_element_count(&self) -> Option<u64> {
2245        match self.backend_repr {
2246            BackendRepr::SimdScalableVector { count, .. } => Some(count),
2247            _ => None,
2248        }
2249    }
2250
2251    /// Returns `true` if the type is a ZST and not unsized.
2252    ///
2253    /// Note that this does *not* imply that the type is irrelevant for layout! It can still have
2254    /// non-trivial alignment constraints. You probably want to use `is_1zst` instead.
2255    pub fn is_zst(&self) -> bool {
2256        match self.backend_repr {
2257            BackendRepr::Scalar(_)
2258            | BackendRepr::ScalarPair(..)
2259            | BackendRepr::SimdScalableVector { .. }
2260            | BackendRepr::SimdVector { .. } => false,
2261            BackendRepr::Memory { sized } => sized && self.size.bytes() == 0,
2262        }
2263    }
2264
2265    /// Checks if these two `Layout` are equal enough to be considered "the same for all function
2266    /// call ABIs". Note however that real ABIs depend on more details that are not reflected in the
2267    /// `Layout`; the `PassMode` need to be compared as well. Also note that we assume
2268    /// aggregates are passed via `PassMode::Indirect` or `PassMode::Cast`; more strict
2269    /// checks would otherwise be required.
2270    pub fn eq_abi(&self, other: &Self) -> bool {
2271        // The one thing that we are not capturing here is that for unsized types, the metadata must
2272        // also have the same ABI, and moreover that the same metadata leads to the same size. The
2273        // 2nd point is quite hard to check though.
2274        self.size == other.size
2275            && self.is_sized() == other.is_sized()
2276            && self.backend_repr.eq_up_to_validity(&other.backend_repr)
2277            && self.backend_repr.is_bool() == other.backend_repr.is_bool()
2278            && self.align.abi == other.align.abi
2279            && self.max_repr_align == other.max_repr_align
2280            && self.unadjusted_abi_align == other.unadjusted_abi_align
2281    }
2282}
2283
2284#[derive(#[automatically_derived]
impl ::core::marker::Copy for StructKind { }Copy, #[automatically_derived]
impl ::core::clone::Clone for StructKind {
    #[inline]
    fn clone(&self) -> StructKind {
        let _: ::core::clone::AssertParamIsClone<Size>;
        let _: ::core::clone::AssertParamIsClone<Align>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for StructKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            StructKind::AlwaysSized =>
                ::core::fmt::Formatter::write_str(f, "AlwaysSized"),
            StructKind::MaybeUnsized =>
                ::core::fmt::Formatter::write_str(f, "MaybeUnsized"),
            StructKind::Prefixed(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f,
                    "Prefixed", __self_0, &__self_1),
        }
    }
}Debug)]
2285pub enum StructKind {
2286    /// A tuple, closure, or univariant which cannot be coerced to unsized.
2287    AlwaysSized,
2288    /// A univariant, the last field of which may be coerced to unsized.
2289    MaybeUnsized,
2290    /// A univariant, but with a prefix of an arbitrary size & alignment (e.g., enum tag).
2291    Prefixed(Size, Align),
2292}
2293
2294#[derive(#[automatically_derived]
impl ::core::clone::Clone for AbiFromStrErr {
    #[inline]
    fn clone(&self) -> AbiFromStrErr {
        match self {
            AbiFromStrErr::Unknown => AbiFromStrErr::Unknown,
            AbiFromStrErr::NoExplicitUnwind =>
                AbiFromStrErr::NoExplicitUnwind,
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for AbiFromStrErr {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                AbiFromStrErr::Unknown => "Unknown",
                AbiFromStrErr::NoExplicitUnwind => "NoExplicitUnwind",
            })
    }
}Debug)]
2295pub enum AbiFromStrErr {
2296    /// not a known ABI
2297    Unknown,
2298    /// no "-unwind" variant can be used here
2299    NoExplicitUnwind,
2300}