Skip to main content

rustc_abi/
lib.rs

1// tidy-alphabetical-start
2#![cfg_attr(feature = "nightly", allow(internal_features))]
3#![cfg_attr(feature = "nightly", feature(rustc_attrs))]
4#![cfg_attr(feature = "nightly", feature(step_trait))]
5// tidy-alphabetical-end
6
7/*! ABI handling for rustc
8
9## What is an "ABI"?
10
11Literally, "application binary interface", which means it is everything about how code interacts,
12at the machine level, with other code. This means it technically covers all of the following:
13- object binary format for e.g. relocations or offset tables
14- in-memory layout of types
15- procedure calling conventions
16
17When we discuss "ABI" in the context of rustc, we are probably discussing calling conventions.
18To describe those `rustc_abi` also covers type layout, as it must for values passed on the stack.
19Despite `rustc_abi` being about calling conventions, it is good to remember these usages exist.
20You will encounter all of them and more if you study target-specific codegen enough!
21Even in general conversation, when someone says "the Rust ABI is unstable", it may allude to
22either or both of
23- `repr(Rust)` types have a mostly-unspecified layout
24- `extern "Rust" fn(A) -> R` has an unspecified calling convention
25
26## Crate Goal
27
28ABI is a foundational concept, so the `rustc_abi` crate serves as an equally foundational crate.
29It cannot carry all details relevant to an ABI: those permeate code generation and linkage.
30Instead, `rustc_abi` is intended to provide the interface for reasoning about the binary interface.
31It should contain traits and types that other crates then use in their implementation.
32For example, a platform's `extern "C" fn` calling convention will be implemented in `rustc_target`
33but `rustc_abi` contains the types for calculating layout and describing register-passing.
34This makes it easier to describe things in the same way across targets, codegen backends, and
35even other Rust compilers, such as rust-analyzer!
36
37*/
38
39use std::cmp::min;
40use std::fmt;
41#[cfg(feature = "nightly")]
42use std::iter::Step;
43use std::num::{NonZero, ParseIntError};
44use std::ops::{Add, AddAssign, Deref, Mul, Sub};
45use std::range::RangeInclusive;
46use std::str::FromStr;
47
48use bitflags::bitflags;
49#[cfg(feature = "nightly")]
50use rustc_data_structures::stable_hash::StableOrd;
51#[cfg(feature = "nightly")]
52use rustc_error_messages::{DiagArgValue, IntoDiagArg};
53#[cfg(feature = "nightly")]
54use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, 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;
68mod wrapping_range;
69
70pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind};
71pub use canon_abi::{ArmCall, CanonAbi, InterruptKind, X86Call};
72#[cfg(feature = "nightly")]
73pub use extern_abi::CVariadicStatus;
74pub use extern_abi::{ExternAbi, all_names};
75pub use layout::{FIRST_VARIANT, FieldIdx, LayoutCalculator, LayoutCalculatorError, VariantIdx};
76#[cfg(feature = "nightly")]
77pub use layout::{Layout, TyAbiInterface, TyAndLayout};
78pub use wrapping_range::WrappingRange;
79
80#[derive(#[automatically_derived]
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)]
81#[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))]
82pub struct ReprFlags(u8);
83
84impl ReprFlags {
    #[allow(deprecated, non_upper_case_globals,)]
    pub const IS_C: Self = Self::from_bits_retain(1 << 0);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const IS_SIMD: Self = Self::from_bits_retain(1 << 1);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const IS_TRANSPARENT: Self = Self::from_bits_retain(1 << 2);
    #[doc = r" Internal only for now. If true, don't reorder fields."]
    #[doc = r" On its own it does not prevent ABI optimizations."]
    #[allow(deprecated, non_upper_case_globals,)]
    pub const IS_LINEAR: Self = Self::from_bits_retain(1 << 3);
    #[doc =
    r" If true, the type's crate has opted into layout randomization."]
    #[doc =
    r" Other flags can still inhibit reordering and thus randomization."]
    #[doc = r" The seed stored in `ReprOptions.field_shuffle_seed`."]
    #[doc = r""]
    #[doc =
    r" `repr(Rust)` structs with only zero-sized fields, single-variant `repr(Rust)` enums with only"]
    #[doc =
    r" zero-sized fields, and zero-variant `repr(Rust)` enums must remain zero-sized as per"]
    #[doc =
    r" T-lang decisions in https://github.com/rust-lang/reference/pull/2262 and https://github.com/rust-lang/reference/pull/2293"]
    #[allow(deprecated, non_upper_case_globals,)]
    pub const RANDOMIZE_LAYOUT: Self = Self::from_bits_retain(1 << 4);
    #[doc =
    r" If true, the type is always passed indirectly by non-Rustic ABIs."]
    #[doc =
    r" See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details."]
    #[allow(deprecated, non_upper_case_globals,)]
    pub const PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS: Self =
        Self::from_bits_retain(1 << 5);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const IS_SCALABLE: Self = Self::from_bits_retain(1 << 6);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const FIELD_ORDER_UNOPTIMIZABLE: Self =
        Self::from_bits_retain(ReprFlags::IS_C.bits() |
                        ReprFlags::IS_SIMD.bits() | ReprFlags::IS_SCALABLE.bits() |
                ReprFlags::IS_LINEAR.bits());
    #[allow(deprecated, non_upper_case_globals,)]
    pub const ABI_UNOPTIMIZABLE: Self =
        Self::from_bits_retain(ReprFlags::IS_C.bits() |
                ReprFlags::IS_SIMD.bits());
}
impl ::bitflags::Flags for ReprFlags {
    const FLAGS: &'static [::bitflags::Flag<ReprFlags>] =
        &[{

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

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

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

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

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

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

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

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

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