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