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