Skip to main content

rustc_middle/mir/interpret/
mod.rs

1//! An interpreter for MIR used in CTFE and by miri.
2
3#[macro_use]
4mod error;
5
6mod allocation;
7mod pointer;
8mod queries;
9mod value;
10
11use std::io::{Read, Write};
12use std::num::NonZero;
13use std::{fmt, io};
14
15use rustc_abi::{AddressSpace, Align, Endian, HasDataLayout, Size};
16use rustc_ast::Mutability;
17use rustc_data_structures::fx::FxHashMap;
18use rustc_data_structures::sharded::ShardedHashMap;
19use rustc_data_structures::sync::{AtomicU64, Lock};
20use rustc_hir::def::DefKind;
21use rustc_hir::def_id::{DefId, LocalDefId};
22use rustc_macros::{StableHash, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
23use rustc_serialize::{Decodable, Encodable};
24use rustc_span::bug;
25use tracing::{debug, trace};
26// Also make the error macros available from this module.
27pub use {
28    err_exhaust, err_inval, err_machine_stop, err_ub, err_ub_format, err_unsup, err_unsup_format,
29    throw_exhaust, throw_inval, throw_machine_stop, throw_ub, throw_ub_format, throw_unsup,
30    throw_unsup_format,
31};
32
33pub use self::allocation::{
34    AllocBytes, AllocError, AllocInit, AllocRange, AllocResult, Allocation, ConstAllocation,
35    InitChunk, InitChunkIter, alloc_range,
36};
37pub use self::error::{
38    BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled, EvalStaticInitializerRawResult,
39    EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, InterpErrorInfo,
40    InterpErrorKind, InterpResult, InvalidMetaKind, InvalidProgramInfo, MachineStopType,
41    Misalignment, ReportedErrorInfo, ResourceExhaustionInfo, UndefinedBehaviorInfo,
42    UnsupportedOpInfo, ValTreeCreationError, interp_ok,
43};
44pub use self::pointer::{CtfeProvenance, Pointer, PointerArithmetic, Provenance};
45pub use self::value::Scalar;
46use crate::mir;
47use crate::ty::codec::{TyDecoder, TyEncoder};
48use crate::ty::print::with_no_trimmed_paths;
49use crate::ty::{self, Instance, Ty, TyCtxt};
50
51/// Uniquely identifies one of the following:
52/// - A constant
53/// - A static
54#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for GlobalId<'tcx> { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl<'tcx> ::core::clone::TrivialClone for GlobalId<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::clone::Clone for GlobalId<'tcx> {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<ty::Instance<'tcx>>;
        let _: ::core::clone::AssertParamIsClone<Option<mir::Promoted>>;
        *self
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for GlobalId<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "GlobalId",
            "instance", &self.instance, "promoted", &&self.promoted)
    }
}Debug, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for GlobalId<'tcx> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<ty::Instance<'tcx>>;
        let _: ::core::cmp::AssertParamIsEq<Option<mir::Promoted>>;
    }
}Eq, #[automatically_derived]
impl<'tcx> ::core::marker::StructuralPartialEq for GlobalId<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for GlobalId<'tcx> {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.instance == other.instance && self.promoted == other.promoted
    }
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::hash::Hash for GlobalId<'tcx> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.instance, state);
        ::core::hash::Hash::hash(&self.promoted, state)
    }
}Hash, const _: () =
    {
        impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
            ::rustc_serialize::Encodable<__E> for GlobalId<'tcx> {
            fn encode(&self, __encoder: &mut __E) {
                let GlobalId {
                        instance: ref __binding_0, promoted: ref __binding_1 } =
                    *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                    __encoder);
            }
        }
    };TyEncodable, const _: () =
    {
        impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
            ::rustc_serialize::Decodable<__D> for GlobalId<'tcx> {
            fn decode(__decoder: &mut __D) -> Self {
                GlobalId {
                    instance: ::rustc_serialize::Decodable::decode(__decoder),
                    promoted: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };TyDecodable)]
55#[derive(const _: () =
    {
        impl<'tcx> ::rustc_data_structures::stable_hash::StableHash for
            GlobalId<'tcx> {
            #[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 {
                    GlobalId {
                        instance: ref __binding_0, promoted: ref __binding_1 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>
            for GlobalId<'tcx> {
            fn try_fold_with<__F: ::rustc_middle::ty::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Result<Self, __F::Error> {
                Ok(match self {
                        GlobalId { instance: __binding_0, promoted: __binding_1 } =>
                            {
                            GlobalId {
                                instance: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_0,
                                        __folder)?,
                                promoted: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_1,
                                        __folder)?,
                            }
                        }
                    })
            }
            fn fold_with<__F: ::rustc_middle::ty::TypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Self {
                match self {
                    GlobalId { instance: __binding_0, promoted: __binding_1 } =>
                        {
                        GlobalId {
                            instance: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_0,
                                __folder),
                            promoted: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_1,
                                __folder),
                        }
                    }
                }
            }
        }
    };TypeFoldable, const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>
            for GlobalId<'tcx> {
            fn visit_with<__V: ::rustc_middle::ty::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>(&self,
                __visitor: &mut __V) -> __V::Result {
                match *self {
                    GlobalId {
                        instance: ref __binding_0, promoted: ref __binding_1 } => {
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_1,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                    }
                }
                <__V::Result as ::rustc_middle::ty::VisitorResult>::output()
            }
        }
    };TypeVisitable)]
56pub struct GlobalId<'tcx> {
57    /// For a constant or static, the `Instance` of the item itself.
58    /// For a promoted global, the `Instance` of the function they belong to.
59    pub instance: ty::Instance<'tcx>,
60
61    /// The index for promoted globals within their function's `mir::Body`.
62    pub promoted: Option<mir::Promoted>,
63}
64
65impl<'tcx> GlobalId<'tcx> {
66    pub fn display(self, tcx: TyCtxt<'tcx>) -> String {
67        let instance_name = {
    let _guard = NoTrimmedGuard::new();
    tcx.def_path_str(self.instance.def.def_id())
}with_no_trimmed_paths!(tcx.def_path_str(self.instance.def.def_id()));
68        if let Some(promoted) = self.promoted {
69            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}::{1:?}", instance_name,
                promoted))
    })format!("{instance_name}::{promoted:?}")
70        } else {
71            instance_name
72        }
73    }
74}
75
76#[derive(#[automatically_derived]
impl ::core::marker::Copy for AllocId { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for AllocId { }
#[automatically_derived]
impl ::core::clone::Clone for AllocId {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<NonZero<u64>>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for AllocId {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<NonZero<u64>>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for AllocId {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.0, state)
    }
}Hash, #[automatically_derived]
impl ::core::cmp::Ord for AllocId {
    #[inline]
    fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
        ::core::cmp::Ord::cmp(&self.0, &other.0)
    }
}Ord, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for AllocId { }
#[automatically_derived]
impl ::core::cmp::PartialEq for AllocId {
    #[inline]
    fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::PartialOrd for AllocId {
    #[inline]
    fn partial_cmp(&self, other: &Self)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
    }
}PartialOrd)]
77pub struct AllocId(pub NonZero<u64>);
78
79// AllocId show up in const-eval error messages
80impl fmt::Display for AllocId {
81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        if f.alternate() { f.write_fmt(format_args!("a{0}", self.0))write!(f, "a{}", self.0) } else { f.write_fmt(format_args!("alloc{0}", self.0))write!(f, "alloc{}", self.0) }
83    }
84}
85
86// We want the `Debug` output to be readable as it is used by `derive(Debug)` for
87// all the Miri types.
88impl fmt::Debug for AllocId {
89    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90        // Dispatch to `Display` impl.
91        fmt::Display::fmt(self, f)
92    }
93}
94
95#[derive(const _: () =
    {
        impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
            ::rustc_serialize::Decodable<__D> for AllocDiscriminant {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { AllocDiscriminant::Alloc }
                    1usize => { AllocDiscriminant::Fn }
                    2usize => { AllocDiscriminant::VTable }
                    3usize => { AllocDiscriminant::Static }
                    4usize => { AllocDiscriminant::Type }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `AllocDiscriminant`, expected 0..5, actual {0}",
                                n));
                    }
                }
            }
        }
    };TyDecodable, const _: () =
    {
        impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
            ::rustc_serialize::Encodable<__E> for AllocDiscriminant {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        AllocDiscriminant::Alloc => { 0usize }
                        AllocDiscriminant::Fn => { 1usize }
                        AllocDiscriminant::VTable => { 2usize }
                        AllocDiscriminant::Static => { 3usize }
                        AllocDiscriminant::Type => { 4usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
            }
        }
    };TyEncodable)]
96enum AllocDiscriminant {
97    Alloc,
98    Fn,
99    VTable,
100    Static,
101    Type,
102}
103
104pub fn specialized_encode_alloc_id<'tcx, E: TyEncoder<'tcx>>(
105    encoder: &mut E,
106    tcx: TyCtxt<'tcx>,
107    alloc_id: AllocId,
108) {
109    match tcx.global_alloc(alloc_id) {
110        GlobalAlloc::Memory(alloc) => {
111            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs:111",
                        "rustc_middle::mir::interpret", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(111u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::mir::interpret"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("encoding {0:?} with {1:#?}",
                                                    alloc_id, alloc) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("encoding {:?} with {:#?}", alloc_id, alloc);
112            AllocDiscriminant::Alloc.encode(encoder);
113            alloc.encode(encoder);
114        }
115        GlobalAlloc::Function { instance } => {
116            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs:116",
                        "rustc_middle::mir::interpret", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(116u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::mir::interpret"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("encoding {0:?} with {1:#?}",
                                                    alloc_id, instance) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("encoding {:?} with {:#?}", alloc_id, instance);
117            AllocDiscriminant::Fn.encode(encoder);
118            instance.encode(encoder);
119        }
120        GlobalAlloc::VTable(ty, poly_trait_ref) => {
121            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs:121",
                        "rustc_middle::mir::interpret", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(121u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::mir::interpret"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("encoding {0:?} with {1:#?}, {2:#?}",
                                                    alloc_id, ty, poly_trait_ref) as
                                            &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("encoding {:?} with {ty:#?}, {poly_trait_ref:#?}", alloc_id);
122            AllocDiscriminant::VTable.encode(encoder);
123            ty.encode(encoder);
124            poly_trait_ref.encode(encoder);
125        }
126        GlobalAlloc::TypeId { ty } => {
127            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs:127",
                        "rustc_middle::mir::interpret", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(127u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::mir::interpret"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("encoding {0:?} with {1:#?}",
                                                    alloc_id, ty) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("encoding {alloc_id:?} with {ty:#?}");
128            AllocDiscriminant::Type.encode(encoder);
129            ty.encode(encoder);
130        }
131        GlobalAlloc::Static(did) => {
132            if !!tcx.is_thread_local_static(did) {
    ::core::panicking::panic("assertion failed: !tcx.is_thread_local_static(did)")
};assert!(!tcx.is_thread_local_static(did));
133            // References to statics doesn't need to know about their allocations,
134            // just about its `DefId`.
135            AllocDiscriminant::Static.encode(encoder);
136            // Cannot use `did.encode(encoder)` because of a bug around
137            // specializations and method calls.
138            Encodable::<E>::encode(&did, encoder);
139        }
140    }
141}
142
143#[derive(#[automatically_derived]
impl ::core::clone::Clone for State {
    #[inline]
    fn clone(&self) -> Self {
        match self {
            Self::Empty => Self::Empty,
            Self::Done(__self_0) =>
                Self::Done(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone)]
144enum State {
145    Empty,
146    Done(AllocId),
147}
148
149pub struct AllocDecodingState {
150    // For each `AllocId`, we keep track of which decoding state it's currently in.
151    decoding_state: Vec<Lock<State>>,
152    // The offsets of each allocation in the data stream.
153    data_offsets: Vec<u64>,
154}
155
156impl AllocDecodingState {
157    #[inline]
158    pub fn new_decoding_session(&self) -> AllocDecodingSession<'_> {
159        AllocDecodingSession { state: self }
160    }
161
162    pub fn new(data_offsets: Vec<u64>) -> Self {
163        let decoding_state =
164            std::iter::repeat_with(|| Lock::new(State::Empty)).take(data_offsets.len()).collect();
165
166        Self { decoding_state, data_offsets }
167    }
168}
169
170#[derive(#[automatically_derived]
impl<'s> ::core::marker::Copy for AllocDecodingSession<'s> { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl<'s> ::core::clone::TrivialClone for AllocDecodingSession<'s> { }
#[automatically_derived]
impl<'s> ::core::clone::Clone for AllocDecodingSession<'s> {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<&'s AllocDecodingState>;
        *self
    }
}Clone)]
171pub struct AllocDecodingSession<'s> {
172    state: &'s AllocDecodingState,
173}
174
175impl<'s> AllocDecodingSession<'s> {
176    /// Decodes an `AllocId` in a thread-safe way.
177    pub fn decode_alloc_id<'tcx, D>(&self, decoder: &mut D) -> AllocId
178    where
179        D: TyDecoder<'tcx>,
180    {
181        // Read the index of the allocation.
182        let idx = usize::try_from(decoder.read_u32()).unwrap();
183        let pos = usize::try_from(self.state.data_offsets[idx]).unwrap();
184
185        // Decode the `AllocDiscriminant` now so that we know if we have to reserve an
186        // `AllocId`.
187        let (alloc_kind, pos) = decoder.with_position(pos, |decoder| {
188            let alloc_kind = AllocDiscriminant::decode(decoder);
189            (alloc_kind, decoder.position())
190        });
191
192        // We are going to hold this lock during the entire decoding of this allocation, which may
193        // require that we decode other allocations. This cannot deadlock for two reasons:
194        //
195        // At the time of writing, it is only possible to create an allocation that contains a pointer
196        // to itself using the const_allocate intrinsic (which is for testing only), and even attempting
197        // to evaluate such consts blows the stack. If we ever grow a mechanism for producing
198        // cyclic allocations, we will need a new strategy for decoding that doesn't bring back
199        // https://github.com/rust-lang/rust/issues/126741.
200        //
201        // It is also impossible to create two allocations (call them A and B) where A is a pointer to B, and B
202        // is a pointer to A, because attempting to evaluate either of those consts will produce a
203        // query cycle, failing compilation.
204        let mut entry = self.state.decoding_state[idx].lock();
205        // Check the decoding state to see if it's already decoded or if we should
206        // decode it here.
207        if let State::Done(alloc_id) = *entry {
208            return alloc_id;
209        }
210
211        // Now decode the actual data.
212        let alloc_id = decoder.with_position(pos, |decoder| match alloc_kind {
213            AllocDiscriminant::Alloc => {
214                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs:214",
                        "rustc_middle::mir::interpret", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(214u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::mir::interpret"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("creating memory alloc ID")
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("creating memory alloc ID");
215                let alloc = <ConstAllocation<'tcx> as Decodable<_>>::decode(decoder);
216                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs:216",
                        "rustc_middle::mir::interpret", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(216u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::mir::interpret"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("decoded alloc {0:?}",
                                                    alloc) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("decoded alloc {:?}", alloc);
217                decoder.interner().reserve_and_set_memory_alloc(alloc)
218            }
219            AllocDiscriminant::Fn => {
220                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs:220",
                        "rustc_middle::mir::interpret", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(220u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::mir::interpret"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("creating fn alloc ID")
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("creating fn alloc ID");
221                let instance = ty::Instance::decode(decoder);
222                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs:222",
                        "rustc_middle::mir::interpret", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(222u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::mir::interpret"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("decoded fn alloc instance: {0:?}",
                                                    instance) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("decoded fn alloc instance: {:?}", instance);
223                decoder.interner().reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT)
224            }
225            AllocDiscriminant::VTable => {
226                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs:226",
                        "rustc_middle::mir::interpret", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(226u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::mir::interpret"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("creating vtable alloc ID")
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("creating vtable alloc ID");
227                let ty = Decodable::decode(decoder);
228                let poly_trait_ref = Decodable::decode(decoder);
229                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs:229",
                        "rustc_middle::mir::interpret", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(229u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::mir::interpret"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("decoded vtable alloc instance: {0:?}, {1:?}",
                                                    ty, poly_trait_ref) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("decoded vtable alloc instance: {ty:?}, {poly_trait_ref:?}");
230                decoder.interner().reserve_and_set_vtable_alloc(ty, poly_trait_ref, CTFE_ALLOC_SALT)
231            }
232            AllocDiscriminant::Type => {
233                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs:233",
                        "rustc_middle::mir::interpret", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(233u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::mir::interpret"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("creating typeid alloc ID")
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("creating typeid alloc ID");
234                let ty = Decodable::decode(decoder);
235                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs:235",
                        "rustc_middle::mir::interpret", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(235u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::mir::interpret"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("decoded typid: {0:?}",
                                                    ty) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("decoded typid: {ty:?}");
236                decoder.interner().reserve_and_set_type_id_alloc(ty)
237            }
238            AllocDiscriminant::Static => {
239                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs:239",
                        "rustc_middle::mir::interpret", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(239u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::mir::interpret"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("creating extern static alloc ID")
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("creating extern static alloc ID");
240                let did = <DefId as Decodable<D>>::decode(decoder);
241                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs:241",
                        "rustc_middle::mir::interpret", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(241u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::mir::interpret"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("decoded static def-ID: {0:?}",
                                                    did) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};trace!("decoded static def-ID: {:?}", did);
242                decoder.interner().reserve_and_set_static_alloc(did)
243            }
244        });
245
246        *entry = State::Done(alloc_id);
247
248        alloc_id
249    }
250}
251
252/// An allocation in the global (tcx-managed) memory can be either a function pointer,
253/// a static, or a "real" allocation with some data in it.
254#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for GlobalAlloc<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::Function { instance: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "Function", "instance", &__self_0),
            Self::VTable(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f, "VTable",
                    __self_0, &__self_1),
            Self::Static(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Static",
                    &__self_0),
            Self::Memory(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Memory",
                    &__self_0),
            Self::TypeId { ty: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "TypeId", "ty", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for GlobalAlloc<'tcx> {
    #[inline]
    fn clone(&self) -> Self {
        match self {
            Self::Function { instance: __self_0 } =>
                Self::Function {
                    instance: ::core::clone::Clone::clone(__self_0),
                },
            Self::VTable(__self_0, __self_1) =>
                Self::VTable(::core::clone::Clone::clone(__self_0),
                    ::core::clone::Clone::clone(__self_1)),
            Self::Static(__self_0) =>
                Self::Static(::core::clone::Clone::clone(__self_0)),
            Self::Memory(__self_0) =>
                Self::Memory(::core::clone::Clone::clone(__self_0)),
            Self::TypeId { ty: __self_0 } =>
                Self::TypeId { ty: ::core::clone::Clone::clone(__self_0) },
        }
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for GlobalAlloc<'tcx> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Instance<'tcx>>;
        let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
        let _:
                ::core::cmp::AssertParamIsEq<&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>>;
        let _: ::core::cmp::AssertParamIsEq<DefId>;
        let _: ::core::cmp::AssertParamIsEq<ConstAllocation<'tcx>>;
        let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
    }
}Eq, #[automatically_derived]
impl<'tcx> ::core::marker::StructuralPartialEq for GlobalAlloc<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for GlobalAlloc<'tcx> {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
                ::core::intrinsics::discriminant_value(other) &&
            match (self, other) {
                (Self::Function { instance: __self_0 }, Self::Function {
                    instance: __arg1_0 }) => __self_0 == __arg1_0,
                (Self::VTable(__self_0, __self_1),
                    Self::VTable(__arg1_0, __arg1_1)) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                (Self::Static(__self_0), Self::Static(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Self::Memory(__self_0), Self::Memory(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Self::TypeId { ty: __self_0 }, Self::TypeId { ty: __arg1_0 })
                    => __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::hash::Hash for GlobalAlloc<'tcx> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
            state);
        match self {
            Self::Function { instance: __self_0 } =>
                ::core::hash::Hash::hash(__self_0, state),
            Self::VTable(__self_0, __self_1) => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state)
            }
            Self::Static(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            Self::Memory(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            Self::TypeId { ty: __self_0 } =>
                ::core::hash::Hash::hash(__self_0, state),
        }
    }
}Hash, const _: () =
    {
        impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
            ::rustc_serialize::Decodable<__D> for GlobalAlloc<'tcx> {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        GlobalAlloc::Function {
                            instance: ::rustc_serialize::Decodable::decode(__decoder),
                        }
                    }
                    1usize => {
                        GlobalAlloc::VTable(::rustc_serialize::Decodable::decode(__decoder),
                            ::rustc_middle::ty::codec::RefDecodable::decode(__decoder))
                    }
                    2usize => {
                        GlobalAlloc::Static(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    3usize => {
                        GlobalAlloc::Memory(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    4usize => {
                        GlobalAlloc::TypeId {
                            ty: ::rustc_serialize::Decodable::decode(__decoder),
                        }
                    }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `GlobalAlloc`, expected 0..5, actual {0}",
                                n));
                    }
                }
            }
        }
    };TyDecodable, const _: () =
    {
        impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
            ::rustc_serialize::Encodable<__E> for GlobalAlloc<'tcx> {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        GlobalAlloc::Function { instance: ref __binding_0 } => {
                            0usize
                        }
                        GlobalAlloc::VTable(ref __binding_0, __binding_1) => {
                            1usize
                        }
                        GlobalAlloc::Static(ref __binding_0) => { 2usize }
                        GlobalAlloc::Memory(ref __binding_0) => { 3usize }
                        GlobalAlloc::TypeId { ty: ref __binding_0 } => { 4usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    GlobalAlloc::Function { instance: ref __binding_0 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    GlobalAlloc::VTable(ref __binding_0, __binding_1) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                    }
                    GlobalAlloc::Static(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    GlobalAlloc::Memory(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    GlobalAlloc::TypeId { ty: ref __binding_0 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };TyEncodable, const _: () =
    {
        impl<'tcx> ::rustc_data_structures::stable_hash::StableHash for
            GlobalAlloc<'tcx> {
            #[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 {
                    GlobalAlloc::Function { instance: ref __binding_0 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    GlobalAlloc::VTable(ref __binding_0, ref __binding_1) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                    GlobalAlloc::Static(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    GlobalAlloc::Memory(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    GlobalAlloc::TypeId { ty: ref __binding_0 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
255pub enum GlobalAlloc<'tcx> {
256    /// The alloc ID is used as a function pointer.
257    Function { instance: Instance<'tcx> },
258    /// This alloc ID points to a symbolic (not-reified) vtable.
259    /// We remember the full dyn type, not just the principal trait, so that
260    /// const-eval and Miri can detect UB due to invalid transmutes of
261    /// `dyn Trait` types.
262    VTable(Ty<'tcx>, &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>),
263    /// The alloc ID points to a "lazy" static variable that did not get computed (yet).
264    /// This is also used to break the cycle in recursive statics.
265    Static(DefId),
266    /// The alloc ID points to memory.
267    Memory(ConstAllocation<'tcx>),
268    /// The first pointer-sized segment of a type id. On 64 bit systems, the 128 bit type id
269    /// is split into two segments, on 32 bit systems there are 4 segments, and so on.
270    TypeId { ty: Ty<'tcx> },
271}
272
273impl<'tcx> GlobalAlloc<'tcx> {
274    /// Panics if the `GlobalAlloc` does not refer to an `GlobalAlloc::Memory`
275    #[track_caller]
276    #[inline]
277    pub fn unwrap_memory(&self) -> ConstAllocation<'tcx> {
278        match *self {
279            GlobalAlloc::Memory(mem) => mem,
280            _ => ::rustc_span::macros::bug_impl(None,
    format_args!("expected memory, got {0:?}", self), Location::caller())bug!("expected memory, got {:?}", self),
281        }
282    }
283
284    /// Panics if the `GlobalAlloc` is not `GlobalAlloc::Function`
285    #[track_caller]
286    #[inline]
287    pub fn unwrap_fn(&self) -> Instance<'tcx> {
288        match *self {
289            GlobalAlloc::Function { instance, .. } => instance,
290            _ => ::rustc_span::macros::bug_impl(None,
    format_args!("expected function, got {0:?}", self), Location::caller())bug!("expected function, got {:?}", self),
291        }
292    }
293
294    /// Panics if the `GlobalAlloc` is not `GlobalAlloc::VTable`
295    #[track_caller]
296    #[inline]
297    pub fn unwrap_vtable(&self) -> (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>) {
298        match *self {
299            GlobalAlloc::VTable(ty, dyn_ty) => (ty, dyn_ty.principal()),
300            _ => ::rustc_span::macros::bug_impl(None,
    format_args!("expected vtable, got {0:?}", self), Location::caller())bug!("expected vtable, got {:?}", self),
301        }
302    }
303
304    /// The address space that this `GlobalAlloc` should be placed in.
305    #[inline]
306    pub fn address_space(&self, cx: &impl HasDataLayout) -> AddressSpace {
307        match self {
308            GlobalAlloc::Function { .. } => cx.data_layout().instruction_address_space,
309            GlobalAlloc::TypeId { .. }
310            | GlobalAlloc::Static(..)
311            | GlobalAlloc::Memory(..)
312            | GlobalAlloc::VTable(..) => AddressSpace::ZERO,
313        }
314    }
315
316    pub fn mutability(&self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Mutability {
317        // Let's see what kind of memory we are.
318        match *self {
319            GlobalAlloc::Static(did) => {
320                let DefKind::Static { safety: _, mutability, nested } = tcx.def_kind(did) else {
321                    ::rustc_span::macros::bug_impl(None, format_args!("impossible case reached"),
    Location::caller())bug!()
322                };
323                if nested {
324                    // Nested statics in a `static` are never interior mutable,
325                    // so just use the declared mutability.
326                    if truecfg!(debug_assertions) {
327                        let alloc = tcx.eval_static_initializer(did).unwrap();
328                        {
    match (&alloc.0.mutability, &mutability) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val, ::core::option::Option::None);
            }
        }
    }
};assert_eq!(alloc.0.mutability, mutability);
329                    }
330                    mutability
331                } else {
332                    let mutability = match mutability {
333                        Mutability::Not
334                            if !tcx
335                                .type_of(did)
336                                .no_bound_vars()
337                                .expect("statics should not have generic parameters")
338                                .is_freeze(tcx, typing_env) =>
339                        {
340                            Mutability::Mut
341                        }
342                        _ => mutability,
343                    };
344                    mutability
345                }
346            }
347            GlobalAlloc::Memory(alloc) => alloc.inner().mutability,
348            GlobalAlloc::TypeId { .. } | GlobalAlloc::Function { .. } | GlobalAlloc::VTable(..) => {
349                // These are immutable.
350                Mutability::Not
351            }
352        }
353    }
354
355    pub fn size_and_align(
356        &self,
357        tcx: TyCtxt<'tcx>,
358        typing_env: ty::TypingEnv<'tcx>,
359    ) -> (Size, Align) {
360        match *self {
361            GlobalAlloc::Static(def_id) => {
362                let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else {
363                    ::rustc_span::macros::bug_impl(None,
    format_args!("GlobalAlloc::Static is not a static"), Location::caller())bug!("GlobalAlloc::Static is not a static")
364                };
365
366                if nested {
367                    // Nested anonymous statics are untyped, so let's get their
368                    // size and alignment from the allocation itself. This always
369                    // succeeds, as the query is fed at DefId creation time, so no
370                    // evaluation actually occurs.
371                    let alloc = tcx.eval_static_initializer(def_id).unwrap();
372                    (alloc.0.size(), alloc.0.align)
373                } else {
374                    // Use size and align of the type for everything else. We need
375                    // to do that to
376                    // * avoid cycle errors in case of self-referential statics,
377                    // * be able to get information on extern statics.
378                    let ty = tcx
379                        .type_of(def_id)
380                        .no_bound_vars()
381                        .expect("statics should not have generic parameters");
382                    let layout = tcx.layout_of(typing_env.as_query_input(ty)).unwrap();
383                    if !layout.is_sized() {
    ::core::panicking::panic("assertion failed: layout.is_sized()")
};assert!(layout.is_sized());
384
385                    // Take over-alignment from attributes into account.
386                    let align = match tcx.codegen_fn_attrs(def_id).alignment {
387                        Some(align_from_attribute) => {
388                            Ord::max(align_from_attribute, layout.align.abi)
389                        }
390                        None => layout.align.abi,
391                    };
392
393                    (layout.size, align)
394                }
395            }
396            GlobalAlloc::Memory(alloc) => {
397                let alloc = alloc.inner();
398                (alloc.size(), alloc.align)
399            }
400            GlobalAlloc::Function { .. } => (Size::ZERO, Align::ONE),
401            GlobalAlloc::VTable(..) => {
402                // No data to be accessed here. But vtables are pointer-aligned.
403                (Size::ZERO, tcx.data_layout.pointer_align().abi)
404            }
405            // Fake allocation, there's nothing to access here.
406            GlobalAlloc::TypeId { .. } => (Size::ZERO, Align::ONE),
407        }
408    }
409}
410
411pub const CTFE_ALLOC_SALT: usize = 0;
412
413pub(crate) struct AllocMap<'tcx> {
414    /// Maps `AllocId`s to their corresponding allocations.
415    // Note that this map on rustc workloads seems to be rather dense, but in miri workloads should
416    // be pretty sparse. In #136105 we considered replacing it with a (dense) Vec-based map, but
417    // since there are workloads where it can be sparse we decided to go with sharding for now. At
418    // least up to 32 cores the one workload tested didn't exhibit much difference between the two.
419    //
420    // Should be locked *after* locking dedup if locking both to avoid deadlocks.
421    to_alloc: ShardedHashMap<AllocId, GlobalAlloc<'tcx>>,
422
423    /// Used to deduplicate global allocations: functions, vtables, string literals, ...
424    ///
425    /// The `usize` is a "salt" used by Miri to make deduplication imperfect, thus better emulating
426    /// the actual guarantees.
427    dedup: Lock<FxHashMap<(GlobalAlloc<'tcx>, usize), AllocId>>,
428
429    /// The `AllocId` to assign to the next requested ID.
430    /// Always incremented; never gets smaller.
431    next_id: AtomicU64,
432}
433
434impl<'tcx> AllocMap<'tcx> {
435    pub(crate) fn new() -> Self {
436        AllocMap {
437            to_alloc: Default::default(),
438            dedup: Default::default(),
439            next_id: AtomicU64::new(1),
440        }
441    }
442    fn reserve(&self) -> AllocId {
443        // Technically there is a window here where we overflow and then another thread
444        // increments `next_id` *again* and uses it before we panic and tear down the entire session.
445        // We consider this fine since such overflows cannot realistically occur.
446        let next_id = self.next_id.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
447        AllocId(NonZero::new(next_id).unwrap())
448    }
449}
450
451impl<'tcx> TyCtxt<'tcx> {
452    /// Obtains a new allocation ID that can be referenced but does not
453    /// yet have an allocation backing it.
454    ///
455    /// Make sure to call `set_alloc_id_memory` or `set_alloc_id_same_memory` before returning such
456    /// an `AllocId` from a query.
457    pub fn reserve_alloc_id(self) -> AllocId {
458        self.alloc_map.reserve()
459    }
460
461    /// Reserves a new ID *if* this allocation has not been dedup-reserved before.
462    /// Should not be used for mutable memory.
463    fn reserve_and_set_dedup(self, alloc: GlobalAlloc<'tcx>, salt: usize) -> AllocId {
464        if let GlobalAlloc::Memory(mem) = alloc {
465            if mem.inner().mutability.is_mut() {
466                ::rustc_span::macros::bug_impl(None,
    format_args!("trying to dedup-reserve mutable memory"),
    Location::caller());bug!("trying to dedup-reserve mutable memory");
467            }
468        }
469        let alloc_salt = (alloc, salt);
470        // Locking this *before* `to_alloc` also to ensure correct lock order.
471        let mut dedup = self.alloc_map.dedup.lock();
472        if let Some(&alloc_id) = dedup.get(&alloc_salt) {
473            return alloc_id;
474        }
475        let id = self.alloc_map.reserve();
476        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs:476",
                        "rustc_middle::mir::interpret", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/d080e7dff1b0fc54541545252818f8cccf995d05/compiler/rustc_middle/src/mir/interpret/mod.rs"),
                        ::tracing_core::__macro_support::Option::Some(476u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::mir::interpret"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("creating alloc {0:?} with id {1:?}",
                                                    alloc_salt.0, id) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("creating alloc {:?} with id {id:?}", alloc_salt.0);
477        // We just reserved, so should always be unique.
478        self.alloc_map.to_alloc.insert_unique(id, alloc_salt.0.clone());
479        dedup.insert(alloc_salt, id);
480        id
481    }
482
483    /// Generates an `AllocId` for a memory allocation. If the exact same memory has been
484    /// allocated before, this will return the same `AllocId`.
485    pub fn reserve_and_set_memory_dedup(self, mem: ConstAllocation<'tcx>, salt: usize) -> AllocId {
486        self.reserve_and_set_dedup(GlobalAlloc::Memory(mem), salt)
487    }
488
489    /// Generates an `AllocId` for a static or return a cached one in case this function has been
490    /// called on the same static before.
491    pub fn reserve_and_set_static_alloc(self, static_id: DefId) -> AllocId {
492        let salt = 0; // Statics have a guaranteed unique address, no salt added.
493        self.reserve_and_set_dedup(GlobalAlloc::Static(static_id), salt)
494    }
495
496    /// Generates an `AllocId` for a function. Will get deduplicated.
497    pub fn reserve_and_set_fn_alloc(self, instance: Instance<'tcx>, salt: usize) -> AllocId {
498        self.reserve_and_set_dedup(GlobalAlloc::Function { instance }, salt)
499    }
500
501    /// Generates an `AllocId` for a (symbolic, not-reified) vtable. Will get deduplicated.
502    pub fn reserve_and_set_vtable_alloc(
503        self,
504        ty: Ty<'tcx>,
505        dyn_ty: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
506        salt: usize,
507    ) -> AllocId {
508        self.reserve_and_set_dedup(GlobalAlloc::VTable(ty, dyn_ty), salt)
509    }
510
511    /// Generates an [AllocId] for a [core::any::TypeId]. Will get deduplicated.
512    pub fn reserve_and_set_type_id_alloc(self, ty: Ty<'tcx>) -> AllocId {
513        self.reserve_and_set_dedup(GlobalAlloc::TypeId { ty }, 0)
514    }
515
516    /// Interns the `Allocation` and return a new `AllocId`, even if there's already an identical
517    /// `Allocation` with a different `AllocId`.
518    /// Statics with identical content will still point to the same `Allocation`, i.e.,
519    /// their data will be deduplicated through `Allocation` interning -- but they
520    /// are different places in memory and as such need different IDs.
521    pub fn reserve_and_set_memory_alloc(self, mem: ConstAllocation<'tcx>) -> AllocId {
522        let id = self.reserve_alloc_id();
523        self.set_alloc_id_memory(id, mem);
524        id
525    }
526
527    /// Returns `None` in case the `AllocId` is dangling. An `InterpretCx` can still have a
528    /// local `Allocation` for that `AllocId`, but having such an `AllocId` in a constant is
529    /// illegal and will likely ICE.
530    /// This function exists to allow const eval to detect the difference between evaluation-
531    /// local dangling pointers and allocations in constants/statics.
532    #[inline]
533    pub fn try_get_global_alloc(self, id: AllocId) -> Option<GlobalAlloc<'tcx>> {
534        self.alloc_map.to_alloc.get(&id)
535    }
536
537    #[inline]
538    #[track_caller]
539    /// Panics in case the `AllocId` is dangling. Since that is impossible for `AllocId`s in
540    /// constants (as all constants must pass interning and validation that check for dangling
541    /// ids), this function is frequently used throughout rustc, but should not be used within
542    /// the interpreter.
543    pub fn global_alloc(self, id: AllocId) -> GlobalAlloc<'tcx> {
544        match self.try_get_global_alloc(id) {
545            Some(alloc) => alloc,
546            None => ::rustc_span::macros::bug_impl(None,
    format_args!("could not find allocation for {0:?}", id),
    Location::caller())bug!("could not find allocation for {id:?}"),
547        }
548    }
549
550    /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
551    /// call this function twice, even with the same `Allocation` will ICE the compiler if
552    /// debug_assertions are enabled.
553    pub fn set_alloc_id_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) {
554        self.alloc_map.to_alloc.insert_unique(id, GlobalAlloc::Memory(mem))
555    }
556
557    /// Freezes an `AllocId` created with `reserve` by pointing it at a static item. Trying to
558    /// call this function twice, even with the same `DefId` will ICE the compiler if
559    /// debug_assertions are enabled.
560    pub fn set_nested_alloc_id_static(self, id: AllocId, def_id: LocalDefId) {
561        self.alloc_map.to_alloc.insert_unique(id, GlobalAlloc::Static(def_id.to_def_id()))
562    }
563}
564
565////////////////////////////////////////////////////////////////////////////////
566// Methods to access integers in the target endianness
567////////////////////////////////////////////////////////////////////////////////
568
569#[inline]
570pub fn write_target_uint(
571    endianness: Endian,
572    mut target: &mut [u8],
573    data: u128,
574) -> Result<(), io::Error> {
575    // This u128 holds an "any-size uint" (since smaller uints can fits in it)
576    // So we do not write all bytes of the u128, just the "payload".
577    match endianness {
578        Endian::Little => target.write(&data.to_le_bytes())?,
579        Endian::Big => target.write(&data.to_be_bytes()[16 - target.len()..])?,
580    };
581    if true {
    if !(target.len() == 0) {
        ::core::panicking::panic("assertion failed: target.len() == 0")
    };
};debug_assert!(target.len() == 0); // We should have filled the target buffer.
582    Ok(())
583}
584
585#[inline]
586pub fn read_target_uint(endianness: Endian, mut source: &[u8]) -> Result<u128, io::Error> {
587    // This u128 holds an "any-size uint" (since smaller uints can fits in it)
588    let mut buf = [0u8; size_of::<u128>()];
589    // So we do not read exactly 16 bytes into the u128, just the "payload".
590    let uint = match endianness {
591        Endian::Little => {
592            source.read_exact(&mut buf[..source.len()])?;
593            Ok(u128::from_le_bytes(buf))
594        }
595        Endian::Big => {
596            source.read_exact(&mut buf[16 - source.len()..])?;
597            Ok(u128::from_be_bytes(buf))
598        }
599    };
600    if true {
    if !(source.len() == 0) {
        ::core::panicking::panic("assertion failed: source.len() == 0")
    };
};debug_assert!(source.len() == 0); // We should have consumed the source buffer.
601    uint
602}