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]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for ReprFlags { }
#[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::marker::StructuralPartialEq for ReprFlags { }
#[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) {
                let ReprFlags(ref __binding_0) = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
            }
        }
    };Encodable_NoContext, const _: () =
    {
        impl<__D: ::rustc_serialize::Decoder>
            ::rustc_serialize::Decodable<__D> for ReprFlags {
            fn decode(__decoder: &mut __D) -> Self {
                ReprFlags(::rustc_serialize::Decodable::decode(__decoder))
            }
        }
    };Decodable_NoContext, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for ReprFlags {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    ReprFlags(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash))]
82pub struct ReprFlags(u8);
83
84impl ReprFlags {
    #[allow(deprecated, non_upper_case_globals,)]
    pub const IS_C: Self = Self::from_bits_retain(1 << 0);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const IS_SIMD: Self = Self::from_bits_retain(1 << 1);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const IS_TRANSPARENT: Self = Self::from_bits_retain(1 << 2);
    #[doc = r" Internal only for now. If true, don't reorder fields."]
    #[doc = r" On its own it does not prevent ABI optimizations."]
    #[allow(deprecated, non_upper_case_globals,)]
    pub const IS_LINEAR: Self = Self::from_bits_retain(1 << 3);
    #[doc =
    r" If true, the type's crate has opted into layout randomization."]
    #[doc =
    r" Other flags can still inhibit reordering and thus randomization."]
    #[doc = r" The seed stored in `ReprOptions.field_shuffle_seed`."]
    #[doc = r""]
    #[doc =
    r" `repr(Rust)` structs with only zero-sized fields, single-variant `repr(Rust)` enums with only"]
    #[doc =
    r" zero-sized fields, and zero-variant `repr(Rust)` enums must remain zero-sized as per"]
    #[doc =
    r" T-lang decisions in https://github.com/rust-lang/reference/pull/2262 and https://github.com/rust-lang/reference/pull/2293"]
    #[allow(deprecated, non_upper_case_globals,)]
    pub const RANDOMIZE_LAYOUT: Self = Self::from_bits_retain(1 << 4);
    #[doc =
    r" If true, the type is always passed indirectly by non-Rustic ABIs."]
    #[doc =
    r" See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details."]
    #[allow(deprecated, non_upper_case_globals,)]
    pub const PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS: Self =
        Self::from_bits_retain(1 << 5);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const IS_SCALABLE: Self = Self::from_bits_retain(1 << 6);
    #[allow(deprecated, non_upper_case_globals,)]
    pub const FIELD_ORDER_UNOPTIMIZABLE: Self =
        Self::from_bits_retain(ReprFlags::IS_C.bits() |
                        ReprFlags::IS_SIMD.bits() | ReprFlags::IS_SCALABLE.bits() |
                ReprFlags::IS_LINEAR.bits());
    #[allow(deprecated, non_upper_case_globals,)]
    pub const ABI_UNOPTIMIZABLE: Self =
        Self::from_bits_retain(ReprFlags::IS_C.bits() |
                ReprFlags::IS_SIMD.bits());
}
impl ::bitflags::Flags for ReprFlags {
    const FLAGS: &'static [::bitflags::Flag<ReprFlags>] =
        &[{

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

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

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

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

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

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

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

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

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