Skip to main content

rustc_abi/
lib.rs

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