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