Skip to main content

rustc_middle/mir/interpret/
error.rs

1use std::any::Any;
2use std::backtrace::Backtrace;
3use std::borrow::Cow;
4use std::{convert, fmt, mem, ops};
5
6use either::Either;
7use rustc_abi::{Align, Size, VariantIdx};
8use rustc_data_structures::sync::Lock;
9use rustc_errors::{DiagArgValue, ErrorGuaranteed, IntoDiagArg};
10use rustc_macros::{StableHash, TyDecodable, TyEncodable};
11use rustc_session::CtfeBacktrace;
12use rustc_span::def_id::DefId;
13use rustc_span::{DUMMY_SP, Span, Symbol};
14
15use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar};
16use crate::diagnostics;
17use crate::mir::interpret::CtfeProvenance;
18use crate::mir::{ConstAlloc, ConstValue};
19use crate::ty::{self, Ty, TyCtxt, ValTree, layout, tls};
20
21#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ErrorHandled {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            ErrorHandled::Reported(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f,
                    "Reported", __self_0, &__self_1),
            ErrorHandled::TooGeneric(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "TooGeneric", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for ErrorHandled { }Copy, #[automatically_derived]
impl ::core::clone::Clone for ErrorHandled {
    #[inline]
    fn clone(&self) -> ErrorHandled {
        let _: ::core::clone::AssertParamIsClone<ReportedErrorInfo>;
        let _: ::core::clone::AssertParamIsClone<Span>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for ErrorHandled {
    #[inline]
    fn eq(&self, other: &ErrorHandled) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (ErrorHandled::Reported(__self_0, __self_1),
                    ErrorHandled::Reported(__arg1_0, __arg1_1)) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                (ErrorHandled::TooGeneric(__self_0),
                    ErrorHandled::TooGeneric(__arg1_0)) => __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ErrorHandled {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<ReportedErrorInfo>;
        let _: ::core::cmp::AssertParamIsEq<Span>;
    }
}Eq, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for ErrorHandled
            {
            #[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 {
                    ErrorHandled::Reported(ref __binding_0, ref __binding_1) =>
                        {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                    ErrorHandled::TooGeneric(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, const _: () =
    {
        impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
            ::rustc_serialize::Encodable<__E> for ErrorHandled {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        ErrorHandled::Reported(ref __binding_0, ref __binding_1) =>
                            {
                            0usize
                        }
                        ErrorHandled::TooGeneric(ref __binding_0) => { 1usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    ErrorHandled::Reported(ref __binding_0, ref __binding_1) =>
                        {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                    }
                    ErrorHandled::TooGeneric(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };TyEncodable, const _: () =
    {
        impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
            ::rustc_serialize::Decodable<__D> for ErrorHandled {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        ErrorHandled::Reported(::rustc_serialize::Decodable::decode(__decoder),
                            ::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => {
                        ErrorHandled::TooGeneric(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `ErrorHandled`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };TyDecodable)]
22pub enum ErrorHandled {
23    /// Already reported an error for this evaluation, and the compilation is
24    /// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`.
25    Reported(ReportedErrorInfo, Span),
26    /// Don't emit an error, the evaluation failed because the MIR was generic
27    /// and the args didn't fully monomorphize it.
28    TooGeneric(Span),
29}
30
31impl From<ReportedErrorInfo> for ErrorHandled {
32    #[inline]
33    fn from(error: ReportedErrorInfo) -> ErrorHandled {
34        ErrorHandled::Reported(error, DUMMY_SP)
35    }
36}
37
38impl ErrorHandled {
39    pub(crate) fn with_span(self, span: Span) -> Self {
40        match self {
41            ErrorHandled::Reported(err, _span) => ErrorHandled::Reported(err, span),
42            ErrorHandled::TooGeneric(_span) => ErrorHandled::TooGeneric(span),
43        }
44    }
45
46    pub fn emit_note(&self, tcx: TyCtxt<'_>) {
47        match self {
48            &ErrorHandled::Reported(err, span) => {
49                if !err.allowed_in_infallible && !span.is_dummy() {
50                    tcx.dcx().emit_note(diagnostics::ErroneousConstant { span });
51                }
52            }
53            &ErrorHandled::TooGeneric(_) => {}
54        }
55    }
56}
57
58#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ReportedErrorInfo {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "ReportedErrorInfo", "error", &self.error,
            "allowed_in_infallible", &&self.allowed_in_infallible)
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for ReportedErrorInfo { }Copy, #[automatically_derived]
impl ::core::clone::Clone for ReportedErrorInfo {
    #[inline]
    fn clone(&self) -> ReportedErrorInfo {
        let _: ::core::clone::AssertParamIsClone<ErrorGuaranteed>;
        let _: ::core::clone::AssertParamIsClone<bool>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for ReportedErrorInfo {
    #[inline]
    fn eq(&self, other: &ReportedErrorInfo) -> bool {
        self.allowed_in_infallible == other.allowed_in_infallible &&
            self.error == other.error
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ReportedErrorInfo {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<ErrorGuaranteed>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for
            ReportedErrorInfo {
            #[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 {
                    ReportedErrorInfo {
                        error: ref __binding_0,
                        allowed_in_infallible: ref __binding_1 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, const _: () =
    {
        impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
            ::rustc_serialize::Encodable<__E> for ReportedErrorInfo {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    ReportedErrorInfo {
                        error: ref __binding_0,
                        allowed_in_infallible: ref __binding_1 } => {
                        ::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 ReportedErrorInfo {
            fn decode(__decoder: &mut __D) -> Self {
                ReportedErrorInfo {
                    error: ::rustc_serialize::Decodable::decode(__decoder),
                    allowed_in_infallible: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };TyDecodable)]
59pub struct ReportedErrorInfo {
60    error: ErrorGuaranteed,
61    /// Whether this error is allowed to show up even in otherwise "infallible" promoteds.
62    /// This is for things like overflows during size computation or resource exhaustion.
63    allowed_in_infallible: bool,
64}
65
66impl ReportedErrorInfo {
67    #[inline]
68    pub fn const_eval_error(error: ErrorGuaranteed) -> ReportedErrorInfo {
69        ReportedErrorInfo { allowed_in_infallible: false, error }
70    }
71
72    /// Use this when the error that led to this is *not* a const-eval error
73    /// (e.g., a layout or type checking error).
74    #[inline]
75    pub fn non_const_eval_error(error: ErrorGuaranteed) -> ReportedErrorInfo {
76        ReportedErrorInfo { allowed_in_infallible: true, error }
77    }
78
79    /// Use this when the error that led to this *is* a const-eval error, but
80    /// we do allow it to occur in infallible constants (e.g., resource exhaustion).
81    #[inline]
82    pub fn allowed_in_infallible(error: ErrorGuaranteed) -> ReportedErrorInfo {
83        ReportedErrorInfo { allowed_in_infallible: true, error }
84    }
85
86    pub fn is_allowed_in_infallible(&self) -> bool {
87        self.allowed_in_infallible
88    }
89}
90
91impl From<ReportedErrorInfo> for ErrorGuaranteed {
92    #[inline]
93    fn from(val: ReportedErrorInfo) -> Self {
94        val.error
95    }
96}
97
98/// An error type for the `const_to_valtree` query. Some error should be reported with a "use-site span",
99/// which means the query cannot emit the error, so those errors are represented as dedicated variants here.
100#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for ValTreeCreationError<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            ValTreeCreationError::NodesOverflow =>
                ::core::fmt::Formatter::write_str(f, "NodesOverflow"),
            ValTreeCreationError::InvalidConst =>
                ::core::fmt::Formatter::write_str(f, "InvalidConst"),
            ValTreeCreationError::NonSupportedType(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "NonSupportedType", &__self_0),
            ValTreeCreationError::CyclicConst =>
                ::core::fmt::Formatter::write_str(f, "CyclicConst"),
            ValTreeCreationError::ErrorHandled(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ErrorHandled", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for ValTreeCreationError<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for ValTreeCreationError<'tcx> {
    #[inline]
    fn clone(&self) -> ValTreeCreationError<'tcx> {
        let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
        let _: ::core::clone::AssertParamIsClone<ErrorHandled>;
        *self
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for ValTreeCreationError<'tcx> {
    #[inline]
    fn eq(&self, other: &ValTreeCreationError<'tcx>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (ValTreeCreationError::NonSupportedType(__self_0),
                    ValTreeCreationError::NonSupportedType(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (ValTreeCreationError::ErrorHandled(__self_0),
                    ValTreeCreationError::ErrorHandled(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for ValTreeCreationError<'tcx> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
        let _: ::core::cmp::AssertParamIsEq<ErrorHandled>;
    }
}Eq, const _: () =
    {
        impl<'tcx> ::rustc_data_structures::stable_hash::StableHash for
            ValTreeCreationError<'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 {
                    ValTreeCreationError::NodesOverflow => {}
                    ValTreeCreationError::InvalidConst => {}
                    ValTreeCreationError::NonSupportedType(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    ValTreeCreationError::CyclicConst => {}
                    ValTreeCreationError::ErrorHandled(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, const _: () =
    {
        impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
            ::rustc_serialize::Encodable<__E> for ValTreeCreationError<'tcx> {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        ValTreeCreationError::NodesOverflow => { 0usize }
                        ValTreeCreationError::InvalidConst => { 1usize }
                        ValTreeCreationError::NonSupportedType(ref __binding_0) => {
                            2usize
                        }
                        ValTreeCreationError::CyclicConst => { 3usize }
                        ValTreeCreationError::ErrorHandled(ref __binding_0) => {
                            4usize
                        }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    ValTreeCreationError::NodesOverflow => {}
                    ValTreeCreationError::InvalidConst => {}
                    ValTreeCreationError::NonSupportedType(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    ValTreeCreationError::CyclicConst => {}
                    ValTreeCreationError::ErrorHandled(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };TyEncodable, const _: () =
    {
        impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
            ::rustc_serialize::Decodable<__D> for ValTreeCreationError<'tcx> {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { ValTreeCreationError::NodesOverflow }
                    1usize => { ValTreeCreationError::InvalidConst }
                    2usize => {
                        ValTreeCreationError::NonSupportedType(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    3usize => { ValTreeCreationError::CyclicConst }
                    4usize => {
                        ValTreeCreationError::ErrorHandled(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `ValTreeCreationError`, expected 0..5, actual {0}",
                                n));
                    }
                }
            }
        }
    };TyDecodable)]
101pub enum ValTreeCreationError<'tcx> {
102    /// The constant is too big to be valtree'd.
103    NodesOverflow,
104    /// The constant references mutable or external memory, so it cannot be valtree'd.
105    InvalidConst,
106    /// Values of this type, or this particular value, are not supported as valtrees.
107    NonSupportedType(Ty<'tcx>),
108    /// Trying to valtree this constant would cause the valtree to have cycles.
109    CyclicConst,
110    /// The error has already been handled by const evaluation.
111    ErrorHandled(ErrorHandled),
112}
113
114impl<'tcx> From<ErrorHandled> for ValTreeCreationError<'tcx> {
115    fn from(err: ErrorHandled) -> Self {
116        ValTreeCreationError::ErrorHandled(err)
117    }
118}
119
120impl<'tcx> From<InterpErrorInfo<'tcx>> for ValTreeCreationError<'tcx> {
121    fn from(err: InterpErrorInfo<'tcx>) -> Self {
122        // An error occurred outside the const-eval query, as part of constructing the valtree. We
123        // don't currently preserve the details of this error, since `InterpErrorInfo` cannot be put
124        // into a query result and it can only be access of some mutable or external memory.
125        let (_kind, backtrace) = err.into_parts();
126        backtrace.print_backtrace();
127        ValTreeCreationError::InvalidConst
128    }
129}
130
131impl<'tcx> ValTreeCreationError<'tcx> {
132    pub(crate) fn with_span(self, span: Span) -> Self {
133        use ValTreeCreationError::*;
134        match self {
135            ErrorHandled(handled) => ErrorHandled(handled.with_span(span)),
136            other => other,
137        }
138    }
139}
140
141pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
142pub type EvalStaticInitializerRawResult<'tcx> = Result<ConstAllocation<'tcx>, ErrorHandled>;
143pub type EvalToConstValueResult<'tcx> = Result<ConstValue, ErrorHandled>;
144pub type EvalToValTreeResult<'tcx> = Result<ValTree<'tcx>, ValTreeCreationError<'tcx>>;
145
146#[cfg(target_pointer_width = "64")]
147const _: [(); 8] = [(); ::std::mem::size_of::<InterpErrorInfo<'_>>()];rustc_data_structures::static_assert_size!(InterpErrorInfo<'_>, 8);
148
149/// Packages the kind of error we got from the const code interpreter
150/// up with a Rust-level backtrace of where the error occurred.
151/// These should always be constructed by calling `.into()` on
152/// an `InterpError`. In `rustc_mir::interpret`, we have `throw_err_*`
153/// macros for this.
154///
155/// Interpreter errors must *not* be silently discarded (that will lead to a panic). Instead,
156/// explicitly call `discard_err` if this is really the right thing to do. Note that if
157/// this happens during const-eval or in Miri, it could lead to a UB error being lost!
158#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for InterpErrorInfo<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f,
            "InterpErrorInfo", &&self.0)
    }
}Debug)]
159pub struct InterpErrorInfo<'tcx>(Box<InterpErrorInfoInner<'tcx>>);
160
161#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for InterpErrorInfoInner<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "InterpErrorInfoInner", "kind", &self.kind, "backtrace",
            &&self.backtrace)
    }
}Debug)]
162struct InterpErrorInfoInner<'tcx> {
163    kind: InterpErrorKind<'tcx>,
164    backtrace: InterpErrorBacktrace,
165}
166
167#[derive(#[automatically_derived]
impl ::core::fmt::Debug for InterpErrorBacktrace {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "InterpErrorBacktrace", "backtrace", &&self.backtrace)
    }
}Debug)]
168pub struct InterpErrorBacktrace {
169    backtrace: Option<Box<Backtrace>>,
170}
171
172impl InterpErrorBacktrace {
173    pub fn new() -> InterpErrorBacktrace {
174        let capture_backtrace = tls::with_opt(|tcx| {
175            if let Some(tcx) = tcx {
176                *Lock::borrow(&tcx.sess.ctfe_backtrace)
177            } else {
178                CtfeBacktrace::Disabled
179            }
180        });
181
182        let backtrace = match capture_backtrace {
183            CtfeBacktrace::Disabled => None,
184            CtfeBacktrace::Capture => Some(Box::new(Backtrace::force_capture())),
185            CtfeBacktrace::Immediate => {
186                // Print it now.
187                let backtrace = Backtrace::force_capture();
188                print_backtrace(&backtrace);
189                None
190            }
191        };
192
193        InterpErrorBacktrace { backtrace }
194    }
195
196    pub fn print_backtrace(&self) {
197        if let Some(backtrace) = self.backtrace.as_ref() {
198            print_backtrace(backtrace);
199        }
200    }
201}
202
203impl<'tcx> InterpErrorInfo<'tcx> {
204    pub fn into_parts(self) -> (InterpErrorKind<'tcx>, InterpErrorBacktrace) {
205        let InterpErrorInfo(InterpErrorInfoInner { kind, backtrace }) = self;
206        (kind, backtrace)
207    }
208
209    pub fn into_kind(self) -> InterpErrorKind<'tcx> {
210        self.0.kind
211    }
212
213    pub fn from_parts(kind: InterpErrorKind<'tcx>, backtrace: InterpErrorBacktrace) -> Self {
214        Self(Box::new(InterpErrorInfoInner { kind, backtrace }))
215    }
216
217    #[inline]
218    pub fn kind(&self) -> &InterpErrorKind<'tcx> {
219        &self.0.kind
220    }
221
222    /// Turn the given error into a human-readable string. Expects the string to be printed, so if
223    /// `RUSTC_CTFE_BACKTRACE` is set this will show a backtrace of the rustc internals that
224    /// triggered the error.
225    ///
226    /// This is NOT the preferred way to render an error; use `report` from `const_eval` instead.
227    /// However, this is useful when error messages appear in ICEs.
228    pub fn to_string(&self) -> String {
229        self.0.backtrace.print_backtrace();
230        self.0.kind.to_string()
231    }
232}
233
234fn print_backtrace(backtrace: &Backtrace) {
235    {
    ::std::io::_eprint(format_args!("\n\nAn error occurred in the MIR interpreter:\n{0}\n",
            backtrace));
};eprintln!("\n\nAn error occurred in the MIR interpreter:\n{backtrace}");
236}
237
238impl From<ErrorHandled> for InterpErrorInfo<'_> {
239    fn from(err: ErrorHandled) -> Self {
240        InterpErrorKind::InvalidProgram(match err {
241            ErrorHandled::Reported(r, _span) => InvalidProgramInfo::AlreadyReported(r),
242            ErrorHandled::TooGeneric(_span) => InvalidProgramInfo::TooGeneric,
243        })
244        .into()
245    }
246}
247
248impl<'tcx> From<InterpErrorKind<'tcx>> for InterpErrorInfo<'tcx> {
249    fn from(kind: InterpErrorKind<'tcx>) -> Self {
250        InterpErrorInfo(Box::new(InterpErrorInfoInner {
251            kind,
252            backtrace: InterpErrorBacktrace::new(),
253        }))
254    }
255}
256
257/// Details of why a pointer had to be in-bounds.
258#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CheckInAllocMsg {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            CheckInAllocMsg::MemoryAccess =>
                ::core::fmt::Formatter::write_str(f, "MemoryAccess"),
            CheckInAllocMsg::InboundsPointerArithmetic =>
                ::core::fmt::Formatter::write_str(f,
                    "InboundsPointerArithmetic"),
            CheckInAllocMsg::Dereferenceable(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Dereferenceable", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for CheckInAllocMsg { }Copy, #[automatically_derived]
impl ::core::clone::Clone for CheckInAllocMsg {
    #[inline]
    fn clone(&self) -> CheckInAllocMsg {
        let _: ::core::clone::AssertParamIsClone<&'static str>;
        *self
    }
}Clone)]
259pub enum CheckInAllocMsg {
260    /// We are accessing memory.
261    MemoryAccess,
262    /// We are doing pointer arithmetic.
263    InboundsPointerArithmetic,
264    /// None of the above -- generic/unspecific inbounds test.
265    /// The string is the subject of the test, e.g. "pointer".
266    Dereferenceable(&'static str),
267}
268
269impl fmt::Display for CheckInAllocMsg {
270    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
271        use CheckInAllocMsg::*;
272        match self {
273            MemoryAccess => f.write_fmt(format_args!("memory access failed"))write!(f, "memory access failed"),
274            InboundsPointerArithmetic => f.write_fmt(format_args!("in-bounds pointer arithmetic failed"))write!(f, "in-bounds pointer arithmetic failed"),
275            Dereferenceable(what) => f.write_fmt(format_args!("{0} not dereferenceable", what))write!(f, "{what} not dereferenceable"),
276        }
277    }
278}
279
280/// Details of which pointer is not aligned.
281#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CheckAlignMsg {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                CheckAlignMsg::AccessedPtr => "AccessedPtr",
                CheckAlignMsg::BasedOn => "BasedOn",
            })
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for CheckAlignMsg { }Copy, #[automatically_derived]
impl ::core::clone::Clone for CheckAlignMsg {
    #[inline]
    fn clone(&self) -> CheckAlignMsg { *self }
}Clone)]
282pub enum CheckAlignMsg {
283    /// The accessed pointer did not have proper alignment.
284    AccessedPtr,
285    /// The access occurred with a place that was based on a misaligned pointer.
286    BasedOn,
287}
288
289#[derive(#[automatically_derived]
impl ::core::fmt::Debug for InvalidMetaKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                InvalidMetaKind::SliceTooBig => "SliceTooBig",
                InvalidMetaKind::TooBig => "TooBig",
            })
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for InvalidMetaKind { }Copy, #[automatically_derived]
impl ::core::clone::Clone for InvalidMetaKind {
    #[inline]
    fn clone(&self) -> InvalidMetaKind { *self }
}Clone)]
290pub enum InvalidMetaKind {
291    /// Size of a `[T]` is too big
292    SliceTooBig,
293    /// Size of a DST is too big
294    TooBig,
295}
296
297impl IntoDiagArg for InvalidMetaKind {
298    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
299        DiagArgValue::Str(Cow::Borrowed(match self {
300            InvalidMetaKind::SliceTooBig => "slice_too_big",
301            InvalidMetaKind::TooBig => "too_big",
302        }))
303    }
304}
305
306/// Details of an access to uninitialized bytes / bad pointer bytes where it is not allowed.
307#[derive(#[automatically_derived]
impl ::core::fmt::Debug for BadBytesAccess {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "BadBytesAccess", "access", &self.access, "bad", &&self.bad)
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for BadBytesAccess {
    #[inline]
    fn clone(&self) -> BadBytesAccess {
        let _: ::core::clone::AssertParamIsClone<AllocRange>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for BadBytesAccess { }Copy)]
308pub struct BadBytesAccess {
309    /// Range of the original memory access.
310    pub access: AllocRange,
311    /// Range of the bad memory that was encountered. (Might not be maximal.)
312    pub bad: AllocRange,
313}
314
315/// Information about a size mismatch.
316#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ScalarSizeMismatch {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "ScalarSizeMismatch", "target_size", &self.target_size,
            "data_size", &&self.data_size)
    }
}Debug)]
317pub struct ScalarSizeMismatch {
318    pub target_size: u64,
319    pub data_size: u64,
320}
321
322/// Information about a misaligned pointer.
323#[derive(#[automatically_derived]
impl ::core::marker::Copy for Misalignment { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Misalignment {
    #[inline]
    fn clone(&self) -> Misalignment {
        let _: ::core::clone::AssertParamIsClone<Align>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::hash::Hash for Misalignment {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.has, state);
        ::core::hash::Hash::hash(&self.required, state)
    }
}Hash, #[automatically_derived]
impl ::core::cmp::PartialEq for Misalignment {
    #[inline]
    fn eq(&self, other: &Misalignment) -> bool {
        self.has == other.has && self.required == other.required
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Misalignment {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Align>;
    }
}Eq, #[automatically_derived]
impl ::core::fmt::Debug for Misalignment {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "Misalignment",
            "has", &self.has, "required", &&self.required)
    }
}Debug)]
324pub struct Misalignment {
325    pub has: Align,
326    pub required: Align,
327}
328
329/// Error information for when the program caused Undefined Behavior.
330#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for UndefinedBehaviorInfo<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            UndefinedBehaviorInfo::Ub(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Ub",
                    &__self_0),
            UndefinedBehaviorInfo::ValidationError {
                orig_ty: __self_0,
                path: __self_1,
                msg: __self_2,
                ptr_bytes_warning: __self_3 } =>
                ::core::fmt::Formatter::debug_struct_field4_finish(f,
                    "ValidationError", "orig_ty", __self_0, "path", __self_1,
                    "msg", __self_2, "ptr_bytes_warning", &__self_3),
            UndefinedBehaviorInfo::Unreachable =>
                ::core::fmt::Formatter::write_str(f, "Unreachable"),
            UndefinedBehaviorInfo::BoundsCheckFailed {
                len: __self_0, index: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "BoundsCheckFailed", "len", __self_0, "index", &__self_1),
            UndefinedBehaviorInfo::DivisionByZero =>
                ::core::fmt::Formatter::write_str(f, "DivisionByZero"),
            UndefinedBehaviorInfo::RemainderByZero =>
                ::core::fmt::Formatter::write_str(f, "RemainderByZero"),
            UndefinedBehaviorInfo::DivisionOverflow =>
                ::core::fmt::Formatter::write_str(f, "DivisionOverflow"),
            UndefinedBehaviorInfo::RemainderOverflow =>
                ::core::fmt::Formatter::write_str(f, "RemainderOverflow"),
            UndefinedBehaviorInfo::PointerArithOverflow =>
                ::core::fmt::Formatter::write_str(f, "PointerArithOverflow"),
            UndefinedBehaviorInfo::ArithOverflow { intrinsic: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "ArithOverflow", "intrinsic", &__self_0),
            UndefinedBehaviorInfo::ShiftOverflow {
                intrinsic: __self_0, shift_amount: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "ShiftOverflow", "intrinsic", __self_0, "shift_amount",
                    &__self_1),
            UndefinedBehaviorInfo::InvalidMeta(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "InvalidMeta", &__self_0),
            UndefinedBehaviorInfo::UnterminatedCString(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "UnterminatedCString", &__self_0),
            UndefinedBehaviorInfo::PointerUseAfterFree(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f,
                    "PointerUseAfterFree", __self_0, &__self_1),
            UndefinedBehaviorInfo::PointerOutOfBounds {
                alloc_id: __self_0,
                alloc_size: __self_1,
                ptr_offset: __self_2,
                inbounds_size: __self_3,
                msg: __self_4 } =>
                ::core::fmt::Formatter::debug_struct_field5_finish(f,
                    "PointerOutOfBounds", "alloc_id", __self_0, "alloc_size",
                    __self_1, "ptr_offset", __self_2, "inbounds_size", __self_3,
                    "msg", &__self_4),
            UndefinedBehaviorInfo::DanglingIntPointer {
                addr: __self_0, inbounds_size: __self_1, msg: __self_2 } =>
                ::core::fmt::Formatter::debug_struct_field3_finish(f,
                    "DanglingIntPointer", "addr", __self_0, "inbounds_size",
                    __self_1, "msg", &__self_2),
            UndefinedBehaviorInfo::AlignmentCheckFailed(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f,
                    "AlignmentCheckFailed", __self_0, &__self_1),
            UndefinedBehaviorInfo::WriteToReadOnly(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "WriteToReadOnly", &__self_0),
            UndefinedBehaviorInfo::DerefFunctionPointer(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "DerefFunctionPointer", &__self_0),
            UndefinedBehaviorInfo::DerefVTablePointer(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "DerefVTablePointer", &__self_0),
            UndefinedBehaviorInfo::DerefVaListPointer(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "DerefVaListPointer", &__self_0),
            UndefinedBehaviorInfo::DerefTypeIdPointer(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "DerefTypeIdPointer", &__self_0),
            UndefinedBehaviorInfo::InvalidBool(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "InvalidBool", &__self_0),
            UndefinedBehaviorInfo::InvalidChar(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "InvalidChar", &__self_0),
            UndefinedBehaviorInfo::InvalidTag(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "InvalidTag", &__self_0),
            UndefinedBehaviorInfo::InvalidFunctionPointer(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "InvalidFunctionPointer", &__self_0),
            UndefinedBehaviorInfo::InvalidVaListPointer(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "InvalidVaListPointer", &__self_0),
            UndefinedBehaviorInfo::InvalidVTablePointer(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "InvalidVTablePointer", &__self_0),
            UndefinedBehaviorInfo::InvalidVTableTrait {
                vtable_dyn_type: __self_0, expected_dyn_type: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "InvalidVTableTrait", "vtable_dyn_type", __self_0,
                    "expected_dyn_type", &__self_1),
            UndefinedBehaviorInfo::InvalidStr(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "InvalidStr", &__self_0),
            UndefinedBehaviorInfo::InvalidUninitBytes(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "InvalidUninitBytes", &__self_0),
            UndefinedBehaviorInfo::DeadLocal =>
                ::core::fmt::Formatter::write_str(f, "DeadLocal"),
            UndefinedBehaviorInfo::ScalarSizeMismatch(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ScalarSizeMismatch", &__self_0),
            UndefinedBehaviorInfo::UninhabitedEnumVariantWritten(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "UninhabitedEnumVariantWritten", &__self_0),
            UndefinedBehaviorInfo::UninhabitedEnumVariantRead(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "UninhabitedEnumVariantRead", &__self_0),
            UndefinedBehaviorInfo::InvalidNichedEnumVariantWritten {
                enum_ty: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "InvalidNichedEnumVariantWritten", "enum_ty", &__self_0),
            UndefinedBehaviorInfo::AbiMismatchArgument {
                arg_idx: __self_0, caller_ty: __self_1, callee_ty: __self_2 }
                =>
                ::core::fmt::Formatter::debug_struct_field3_finish(f,
                    "AbiMismatchArgument", "arg_idx", __self_0, "caller_ty",
                    __self_1, "callee_ty", &__self_2),
            UndefinedBehaviorInfo::AbiMismatchReturn {
                caller_ty: __self_0, callee_ty: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "AbiMismatchReturn", "caller_ty", __self_0, "callee_ty",
                    &__self_1),
            UndefinedBehaviorInfo::VaArgOutOfBounds =>
                ::core::fmt::Formatter::write_str(f, "VaArgOutOfBounds"),
            UndefinedBehaviorInfo::CVariadicMismatch {
                caller_is_c_variadic: __self_0, callee_is_c_variadic: __self_1
                } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "CVariadicMismatch", "caller_is_c_variadic", __self_0,
                    "callee_is_c_variadic", &__self_1),
            UndefinedBehaviorInfo::CVariadicFixedCountMismatch {
                caller: __self_0, callee: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "CVariadicFixedCountMismatch", "caller", __self_0, "callee",
                    &__self_1),
        }
    }
}Debug)]
331pub enum UndefinedBehaviorInfo<'tcx> {
332    /// Free-form case. Only for errors that are never caught! Used by miri
333    Ub(String),
334    /// Validation error.
335    ValidationError {
336        orig_ty: Ty<'tcx>,
337        path: Option<String>,
338        msg: String,
339        ptr_bytes_warning: bool,
340    },
341
342    /// Unreachable code was executed.
343    Unreachable,
344    /// A slice/array index projection went out-of-bounds.
345    BoundsCheckFailed { len: u64, index: u64 },
346    /// Something was divided by 0 (x / 0).
347    DivisionByZero,
348    /// Something was "remainded" by 0 (x % 0).
349    RemainderByZero,
350    /// Signed division overflowed (INT_MIN / -1).
351    DivisionOverflow,
352    /// Signed remainder overflowed (INT_MIN % -1).
353    RemainderOverflow,
354    /// Overflowing inbounds pointer arithmetic.
355    PointerArithOverflow,
356    /// Overflow in arithmetic that may not overflow.
357    ArithOverflow { intrinsic: Symbol },
358    /// Shift by too much.
359    ShiftOverflow { intrinsic: Symbol, shift_amount: Either<u128, i128> },
360    /// Invalid metadata in a wide pointer
361    InvalidMeta(InvalidMetaKind),
362    /// Reading a C string that does not end within its allocation.
363    UnterminatedCString(Pointer<AllocId>),
364    /// Using a pointer after it got freed.
365    PointerUseAfterFree(AllocId, CheckInAllocMsg),
366    /// Used a pointer outside the bounds it is valid for.
367    PointerOutOfBounds {
368        alloc_id: AllocId,
369        alloc_size: Size,
370        ptr_offset: i64,
371        /// The size of the memory range that was expected to be in-bounds.
372        inbounds_size: i64,
373        msg: CheckInAllocMsg,
374    },
375    /// Using an integer as a pointer in the wrong way.
376    DanglingIntPointer {
377        addr: u64,
378        /// The size of the memory range that was expected to be in-bounds (or 0 if we need an
379        /// allocation but not any actual memory there, e.g. for function pointers).
380        inbounds_size: i64,
381        msg: CheckInAllocMsg,
382    },
383    /// Used a pointer with bad alignment.
384    AlignmentCheckFailed(Misalignment, CheckAlignMsg),
385    /// Writing to read-only memory.
386    WriteToReadOnly(AllocId),
387    /// Trying to access the data behind a function pointer.
388    DerefFunctionPointer(AllocId),
389    /// Trying to access the data behind a vtable pointer.
390    DerefVTablePointer(AllocId),
391    /// Trying to access the data behind a va_list pointer.
392    DerefVaListPointer(AllocId),
393    /// Trying to access the actual type id.
394    DerefTypeIdPointer(AllocId),
395    /// Using a non-boolean `u8` as bool.
396    InvalidBool(u8),
397    /// Using a non-character `u32` as character.
398    InvalidChar(u32),
399    /// The tag of an enum does not encode an actual discriminant.
400    InvalidTag(Scalar<AllocId>),
401    /// Using a pointer-not-to-a-function as function pointer.
402    InvalidFunctionPointer(Pointer<AllocId>),
403    /// Using a pointer-not-to-a-va-list as variable argument list pointer.
404    InvalidVaListPointer(Pointer<AllocId>),
405    /// Using a pointer-not-to-a-vtable as vtable pointer.
406    InvalidVTablePointer(Pointer<Option<AllocId>>),
407    /// Using a vtable for the wrong trait.
408    InvalidVTableTrait {
409        /// The vtable that was actually referenced by the wide pointer metadata.
410        vtable_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
411        /// The vtable that was expected at the point in MIR that it was accessed.
412        expected_dyn_type: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
413    },
414    /// Using a string that is not valid UTF-8,
415    InvalidStr(std::str::Utf8Error),
416    /// Using uninitialized data where it is not allowed.
417    InvalidUninitBytes(Option<(AllocId, BadBytesAccess)>),
418    /// Working with a local that is not currently live.
419    DeadLocal,
420    /// Data size is not equal to target size.
421    ScalarSizeMismatch(ScalarSizeMismatch),
422    /// A discriminant of an uninhabited enum variant is written.
423    UninhabitedEnumVariantWritten(VariantIdx),
424    /// An uninhabited enum variant is projected.
425    UninhabitedEnumVariantRead(Option<VariantIdx>),
426    /// Trying to set discriminant to the niched variant, but the value does not match.
427    InvalidNichedEnumVariantWritten { enum_ty: Ty<'tcx> },
428    /// ABI-incompatible argument types.
429    AbiMismatchArgument {
430        /// The index of the argument whose type is wrong.
431        arg_idx: usize,
432        caller_ty: Ty<'tcx>,
433        callee_ty: Ty<'tcx>,
434    },
435    /// ABI-incompatible return types.
436    AbiMismatchReturn { caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx> },
437    /// `va_arg` was called on an exhausted `VaList`.
438    VaArgOutOfBounds,
439    /// The caller and callee disagree on whether they are c-variadic or not.
440    CVariadicMismatch { caller_is_c_variadic: bool, callee_is_c_variadic: bool },
441    /// The caller and callee disagree on the number of fixed (i.e. non-c-variadic) arguments.
442    CVariadicFixedCountMismatch { caller: u32, callee: u32 },
443}
444
445impl<'tcx> fmt::Display for UndefinedBehaviorInfo<'tcx> {
446    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
447        use UndefinedBehaviorInfo::*;
448
449        fn fmt_in_alloc_attempt(
450            f: &mut fmt::Formatter<'_>,
451            msg: CheckInAllocMsg,
452            inbounds_size: i64,
453        ) -> fmt::Result {
454            let inbounds_size_fmt = if inbounds_size == 1 {
455                format_args!("1 byte")format_args!("1 byte")
456            } else {
457                format_args!("{0} bytes", inbounds_size)format_args!("{inbounds_size} bytes")
458            };
459            f.write_fmt(format_args!("{0}: ", msg))write!(f, "{msg}: ")?;
460            match msg {
461                CheckInAllocMsg::MemoryAccess => {
462                    f.write_fmt(format_args!("attempting to access {0}", inbounds_size_fmt))write!(f, "attempting to access {inbounds_size_fmt}")
463                }
464                CheckInAllocMsg::InboundsPointerArithmetic => {
465                    f.write_fmt(format_args!("attempting to offset pointer by {0}",
        inbounds_size_fmt))write!(f, "attempting to offset pointer by {inbounds_size_fmt}")
466                }
467                CheckInAllocMsg::Dereferenceable(what) if inbounds_size == 0 => {
468                    f.write_fmt(format_args!("{0} must point to some allocation", what))write!(f, "{what} must point to some allocation")
469                }
470                CheckInAllocMsg::Dereferenceable(what) => {
471                    f.write_fmt(format_args!("{0} must be dereferenceable for {1}", what,
        inbounds_size_fmt))write!(f, "{what} must be dereferenceable for {inbounds_size_fmt}")
472                }
473            }
474        }
475
476        match self {
477            Ub(msg) => f.write_fmt(format_args!("{0}", msg))write!(f, "{msg}"),
478
479            ValidationError { orig_ty, path: None, msg, .. } => {
480                f.write_fmt(format_args!("constructing invalid value of type {0}: {1}",
        orig_ty, msg))write!(f, "constructing invalid value of type {orig_ty}: {msg}")
481            }
482            ValidationError { orig_ty, path: Some(path), msg, .. } => {
483                f.write_fmt(format_args!("constructing invalid value of type {0}: at {1}, {2}",
        orig_ty, path, msg))write!(f, "constructing invalid value of type {orig_ty}: at {path}, {msg}")
484            }
485
486            Unreachable => f.write_fmt(format_args!("entering unreachable code"))write!(f, "entering unreachable code"),
487            BoundsCheckFailed { len, index } => {
488                f.write_fmt(format_args!("indexing out of bounds: the len is {0} but the index is {1}",
        len, index))write!(f, "indexing out of bounds: the len is {len} but the index is {index}")
489            }
490            DivisionByZero => f.write_fmt(format_args!("dividing by zero"))write!(f, "dividing by zero"),
491            RemainderByZero => f.write_fmt(format_args!("calculating the remainder with a divisor of zero"))write!(f, "calculating the remainder with a divisor of zero"),
492            DivisionOverflow => f.write_fmt(format_args!("overflow in signed division (dividing MIN by -1)"))write!(f, "overflow in signed division (dividing MIN by -1)"),
493            RemainderOverflow => f.write_fmt(format_args!("overflow in signed remainder (dividing MIN by -1)"))write!(f, "overflow in signed remainder (dividing MIN by -1)"),
494            PointerArithOverflow => f.write_fmt(format_args!("overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`"))write!(
495                f,
496                "overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`"
497            ),
498            ArithOverflow { intrinsic } => f.write_fmt(format_args!("arithmetic overflow in `{0}`", intrinsic))write!(f, "arithmetic overflow in `{intrinsic}`"),
499            ShiftOverflow { shift_amount, intrinsic } => {
500                f.write_fmt(format_args!("overflowing shift by {0} in `{1}`", shift_amount,
        intrinsic))write!(f, "overflowing shift by {shift_amount} in `{intrinsic}`")
501            }
502            InvalidMeta(InvalidMetaKind::SliceTooBig) => f.write_fmt(format_args!("invalid metadata in wide pointer: slice is bigger than largest supported object"))write!(
503                f,
504                "invalid metadata in wide pointer: slice is bigger than largest supported object"
505            ),
506            InvalidMeta(InvalidMetaKind::TooBig) => f.write_fmt(format_args!("invalid metadata in wide pointer: total size is bigger than largest supported object"))write!(
507                f,
508                "invalid metadata in wide pointer: total size is bigger than largest supported object"
509            ),
510            UnterminatedCString(ptr) => f.write_fmt(format_args!("reading a null-terminated string starting at {0} with no null found before end of allocation",
        ptr))write!(
511                f,
512                "reading a null-terminated string starting at {ptr} with no null found before end of allocation"
513            ),
514            PointerUseAfterFree(alloc_id, msg) => {
515                f.write_fmt(format_args!("{0}: {1} has been freed, so this pointer is dangling",
        msg, alloc_id))write!(f, "{msg}: {alloc_id} has been freed, so this pointer is dangling")
516            }
517            &PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, inbounds_size, msg } => {
518                fmt_in_alloc_attempt(f, msg, inbounds_size)?;
519                f.write_fmt(format_args!(", but got "))write!(f, ", but got ")?;
520                // Write pointer. Offset might be negative so we cannot use the normal `impl Display
521                // for Pointer`.
522                f.write_fmt(format_args!("{0}", alloc_id))write!(f, "{}", alloc_id)?;
523                if ptr_offset > 0 {
524                    f.write_fmt(format_args!("+{0:#x}", ptr_offset))write!(f, "+{:#x}", ptr_offset)?;
525                } else if ptr_offset < 0 {
526                    f.write_fmt(format_args!("-{0:#x}", ptr_offset.unsigned_abs()))write!(f, "-{:#x}", ptr_offset.unsigned_abs())?;
527                }
528                // Write why it is invalid.
529                f.write_fmt(format_args!(" which "))write!(f, " which ")?;
530                if ptr_offset < 0 {
531                    f.write_fmt(format_args!("points to before the beginning of the allocation"))write!(f, "points to before the beginning of the allocation")
532                } else if inbounds_size < 0 {
533                    // We expected the ptr to have memory to its left, but it does not.
534                    if ptr_offset == 0 {
535                        f.write_fmt(format_args!("is at the beginning of the allocation"))write!(f, "is at the beginning of the allocation")
536                    } else {
537                        f.write_fmt(format_args!("is only {0} bytes from the beginning of the allocation",
        ptr_offset))write!(f, "is only {ptr_offset} bytes from the beginning of the allocation")
538                    }
539                } else {
540                    let ptr_offset = ptr_offset as u64;
541                    let alloc_size = alloc_size.bytes();
542                    if ptr_offset >= alloc_size {
543                        let size = if alloc_size == 1 {
544                            format_args!("1 byte")format_args!("1 byte")
545                        } else {
546                            format_args!("{0} bytes", alloc_size)format_args!("{alloc_size} bytes")
547                        };
548                        f.write_fmt(format_args!("is at or beyond the end of the allocation of size {0}",
        size))write!(f, "is at or beyond the end of the allocation of size {size}",)
549                    } else {
550                        let dist_to_end = alloc_size - ptr_offset;
551                        let dist = if dist_to_end == 1 {
552                            format_args!("1 byte")format_args!("1 byte")
553                        } else {
554                            format_args!("{0} bytes", dist_to_end)format_args!("{dist_to_end} bytes")
555                        };
556                        f.write_fmt(format_args!("is only {0} from the end of the allocation", dist))write!(f, "is only {dist} from the end of the allocation",)
557                    }
558                }
559            }
560            &DanglingIntPointer { addr: 0, inbounds_size, msg } => {
561                fmt_in_alloc_attempt(f, msg, inbounds_size)?;
562                f.write_fmt(format_args!(", but got null pointer"))write!(f, ", but got null pointer")
563            }
564            &DanglingIntPointer { addr, inbounds_size, msg } => {
565                fmt_in_alloc_attempt(f, msg, inbounds_size)?;
566                f.write_fmt(format_args!(", but got {0} which is a dangling pointer (it has no provenance)",
        Pointer::<Option<CtfeProvenance>>::without_provenance(addr)))write!(
567                    f,
568                    ", but got {ptr} which is a dangling pointer (it has no provenance)",
569                    ptr = Pointer::<Option<CtfeProvenance>>::without_provenance(addr),
570                )
571            }
572            AlignmentCheckFailed(misalign, msg) => {
573                f.write_fmt(format_args!("{0} with alignment {1}, but alignment {2} is required",
        match msg {
            CheckAlignMsg::AccessedPtr => "accessing memory",
            CheckAlignMsg::BasedOn => "accessing memory based on pointer",
        }, misalign.has.bytes(), misalign.required.bytes()))write!(
574                    f,
575                    "{acc} with alignment {has}, but alignment {required} is required",
576                    acc = match msg {
577                        CheckAlignMsg::AccessedPtr => "accessing memory",
578                        CheckAlignMsg::BasedOn => "accessing memory based on pointer",
579                    },
580                    has = misalign.has.bytes(),
581                    required = misalign.required.bytes(),
582                )
583            }
584            WriteToReadOnly(alloc) => f.write_fmt(format_args!("writing to {0} which is read-only", alloc))write!(f, "writing to {alloc} which is read-only"),
585            DerefFunctionPointer(alloc) => {
586                f.write_fmt(format_args!("accessing {0} which contains a function", alloc))write!(f, "accessing {alloc} which contains a function")
587            }
588            DerefVTablePointer(alloc) => f.write_fmt(format_args!("accessing {0} which contains a vtable", alloc))write!(f, "accessing {alloc} which contains a vtable"),
589            DerefVaListPointer(alloc) => {
590                f.write_fmt(format_args!("accessing {0} which contains a variable argument list",
        alloc))write!(f, "accessing {alloc} which contains a variable argument list")
591            }
592            DerefTypeIdPointer(alloc) => f.write_fmt(format_args!("accessing {0} which contains a `TypeId`", alloc))write!(f, "accessing {alloc} which contains a `TypeId`"),
593            InvalidBool(value) => {
594                f.write_fmt(format_args!("interpreting an invalid 8-bit value as a bool: 0x{0:02x}",
        value))write!(f, "interpreting an invalid 8-bit value as a bool: 0x{value:02x}")
595            }
596            InvalidChar(value) => {
597                f.write_fmt(format_args!("interpreting an invalid 32-bit value as a char: 0x{0:08x}",
        value))write!(f, "interpreting an invalid 32-bit value as a char: 0x{value:08x}")
598            }
599            InvalidTag(tag) => f.write_fmt(format_args!("enum value has invalid tag: {0:x}", tag))write!(f, "enum value has invalid tag: {tag:x}"),
600            InvalidFunctionPointer(ptr) => {
601                f.write_fmt(format_args!("using {0} as function pointer but it does not point to a function",
        ptr))write!(f, "using {ptr} as function pointer but it does not point to a function")
602            }
603            InvalidVaListPointer(ptr) => f.write_fmt(format_args!("using {0} as variable argument list pointer but it does not point to a variable argument list",
        ptr))write!(
604                f,
605                "using {ptr} as variable argument list pointer but it does not point to a variable argument list"
606            ),
607            InvalidVTablePointer(ptr) => {
608                f.write_fmt(format_args!("using {0} as vtable pointer but it does not point to a vtable",
        ptr))write!(f, "using {ptr} as vtable pointer but it does not point to a vtable")
609            }
610            InvalidVTableTrait { vtable_dyn_type, expected_dyn_type } => f.write_fmt(format_args!("using vtable for `{0}` but `{1}` was expected",
        vtable_dyn_type, expected_dyn_type))write!(
611                f,
612                "using vtable for `{vtable_dyn_type}` but `{expected_dyn_type}` was expected"
613            ),
614            InvalidStr(err) => f.write_fmt(format_args!("this string is not valid UTF-8: {0}", err))write!(f, "this string is not valid UTF-8: {err}"),
615            InvalidUninitBytes(None) => {
616                f.write_fmt(format_args!("using uninitialized data, but this operation requires initialized memory"))write!(
617                    f,
618                    "using uninitialized data, but this operation requires initialized memory"
619                )
620            }
621            InvalidUninitBytes(Some((alloc, info))) => f.write_fmt(format_args!("reading memory at {2}{0}, but memory is uninitialized at {1}, and this operation requires initialized memory",
        info.access, info.bad, alloc))write!(
622                f,
623                "reading memory at {alloc}{access}, but memory is uninitialized at {uninit}, and this operation requires initialized memory",
624                access = info.access,
625                uninit = info.bad,
626            ),
627            DeadLocal => f.write_fmt(format_args!("accessing a dead local variable"))write!(f, "accessing a dead local variable"),
628            ScalarSizeMismatch(mismatch) => f.write_fmt(format_args!("scalar size mismatch: expected {0} bytes but got {1} bytes instead",
        mismatch.target_size, mismatch.data_size))write!(
629                f,
630                "scalar size mismatch: expected {target_size} bytes but got {data_size} bytes instead",
631                target_size = mismatch.target_size,
632                data_size = mismatch.data_size,
633            ),
634            UninhabitedEnumVariantWritten(_) => {
635                f.write_fmt(format_args!("writing discriminant of an uninhabited enum variant"))write!(f, "writing discriminant of an uninhabited enum variant")
636            }
637            UninhabitedEnumVariantRead(_) => {
638                f.write_fmt(format_args!("read discriminant of an uninhabited enum variant"))write!(f, "read discriminant of an uninhabited enum variant")
639            }
640            InvalidNichedEnumVariantWritten { enum_ty } => {
641                f.write_fmt(format_args!("trying to set discriminant of a {0} to the niched variant, but the value does not match",
        enum_ty))write!(
642                    f,
643                    "trying to set discriminant of a {enum_ty} to the niched variant, but the value does not match"
644                )
645            }
646            AbiMismatchArgument { arg_idx, caller_ty, callee_ty } => f.write_fmt(format_args!("calling a function whose parameter #{0} has type {1} passing argument of type {2}",
        arg_idx + 1, callee_ty, caller_ty))write!(
647                f,
648                "calling a function whose parameter #{arg_idx} has type {callee_ty} passing argument of type {caller_ty}",
649                arg_idx = arg_idx + 1, // adjust for 1-indexed lists in output
650            ),
651            AbiMismatchReturn { caller_ty, callee_ty } => f.write_fmt(format_args!("calling a function with return type {0} passing return place of type {1}",
        callee_ty, caller_ty))write!(
652                f,
653                "calling a function with return type {callee_ty} passing return place of type {caller_ty}"
654            ),
655            VaArgOutOfBounds => f.write_fmt(format_args!("more C-variadic arguments read than were passed"))write!(f, "more C-variadic arguments read than were passed"),
656            CVariadicMismatch { .. } => f.write_fmt(format_args!("calling a function where the caller and callee disagree on whether the function is C-variadic"))write!(
657                f,
658                "calling a function where the caller and callee disagree on whether the function is C-variadic"
659            ),
660            CVariadicFixedCountMismatch { caller, callee } => f.write_fmt(format_args!("calling a C-variadic function with {0} fixed arguments, but the function expects {1}",
        caller, callee))write!(
661                f,
662                "calling a C-variadic function with {caller} fixed arguments, but the function expects {callee}"
663            ),
664        }
665    }
666}
667
668/// Error information for when the program we executed turned out not to actually be a valid
669/// program. This cannot happen in stand-alone Miri (except for layout errors that are only detect
670/// during monomorphization), but it can happen during CTFE/ConstProp where we work on generic code
671/// or execution does not have all information available.
672#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for InvalidProgramInfo<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            InvalidProgramInfo::TooGeneric =>
                ::core::fmt::Formatter::write_str(f, "TooGeneric"),
            InvalidProgramInfo::AlreadyReported(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "AlreadyReported", &__self_0),
            InvalidProgramInfo::Layout(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Layout",
                    &__self_0),
        }
    }
}Debug)]
673pub enum InvalidProgramInfo<'tcx> {
674    /// Resolution can fail if we are in a too generic context.
675    TooGeneric,
676    /// Abort in case errors are already reported.
677    AlreadyReported(ReportedErrorInfo),
678    /// An error occurred during layout computation.
679    Layout(layout::LayoutError<'tcx>),
680}
681
682impl<'tcx> fmt::Display for InvalidProgramInfo<'tcx> {
683    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
684        use InvalidProgramInfo::*;
685        match self {
686            TooGeneric => f.write_fmt(format_args!("encountered overly generic constant"))write!(f, "encountered overly generic constant"),
687            AlreadyReported(_) => {
688                f.write_fmt(format_args!("an error has already been reported elsewhere (this should not usually be printed)"))write!(
689                    f,
690                    "an error has already been reported elsewhere (this should not usually be printed)"
691                )
692            }
693            Layout(e) => f.write_fmt(format_args!("{0}", e))write!(f, "{e}"),
694        }
695    }
696}
697
698/// Error information for when the program did something that might (or might not) be correct
699/// to do according to the Rust spec, but due to limitations in the interpreter, the
700/// operation could not be carried out. These limitations can differ between CTFE and the
701/// Miri engine, e.g., CTFE does not support dereferencing pointers at integral addresses.
702#[derive(#[automatically_derived]
impl ::core::fmt::Debug for UnsupportedOpInfo {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            UnsupportedOpInfo::Unsupported(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Unsupported", &__self_0),
            UnsupportedOpInfo::UnsizedLocal =>
                ::core::fmt::Formatter::write_str(f, "UnsizedLocal"),
            UnsupportedOpInfo::ExternTypeField =>
                ::core::fmt::Formatter::write_str(f, "ExternTypeField"),
            UnsupportedOpInfo::ReadPartialPointer(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ReadPartialPointer", &__self_0),
            UnsupportedOpInfo::ReadPointerAsInt(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ReadPointerAsInt", &__self_0),
            UnsupportedOpInfo::ThreadLocalStatic(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ThreadLocalStatic", &__self_0),
            UnsupportedOpInfo::ExternStatic(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ExternStatic", &__self_0),
        }
    }
}Debug)]
703pub enum UnsupportedOpInfo {
704    /// Free-form case. Only for errors that are never caught! Used by Miri.
705    // FIXME still use translatable diagnostics
706    Unsupported(String),
707    /// Unsized local variables.
708    UnsizedLocal,
709    /// Extern type field with an indeterminate offset.
710    ExternTypeField,
711    //
712    // The variants below are only reachable from CTFE/const prop, miri will never emit them.
713    //
714    /// Attempting to read or copy parts of a pointer to somewhere else; without knowing absolute
715    /// addresses, the resulting state cannot be represented by the CTFE interpreter.
716    ReadPartialPointer(Pointer<AllocId>),
717    /// Encountered a pointer where we needed an integer.
718    ReadPointerAsInt(Option<(AllocId, BadBytesAccess)>),
719    /// Accessing thread local statics
720    ThreadLocalStatic(DefId),
721    /// Accessing an unsupported extern static.
722    ExternStatic(DefId),
723}
724
725impl fmt::Display for UnsupportedOpInfo {
726    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
727        use UnsupportedOpInfo::*;
728        match self {
729            Unsupported(s) => f.write_fmt(format_args!("{0}", s))write!(f, "{s}"),
730            ExternTypeField => {
731                f.write_fmt(format_args!("`extern type` field does not have a known offset"))write!(f, "`extern type` field does not have a known offset")
732            }
733            UnsizedLocal => f.write_fmt(format_args!("unsized locals are not supported"))write!(f, "unsized locals are not supported"),
734            ReadPartialPointer(ptr) => {
735                f.write_fmt(format_args!("unable to read parts of a pointer from memory at {0}",
        ptr))write!(f, "unable to read parts of a pointer from memory at {ptr}")
736            }
737            ReadPointerAsInt(_) => f.write_fmt(format_args!("unable to turn pointer into integer"))write!(f, "unable to turn pointer into integer"),
738            &ThreadLocalStatic(did) => {
739                f.write_fmt(format_args!("cannot access thread local static `{0}`",
        ty::tls::with(|tcx| tcx.def_path_str(did))))write!(
740                    f,
741                    "cannot access thread local static `{did}`",
742                    did = ty::tls::with(|tcx| tcx.def_path_str(did))
743                )
744            }
745            &ExternStatic(did) => {
746                f.write_fmt(format_args!("cannot access extern static `{0}`",
        ty::tls::with(|tcx| tcx.def_path_str(did))))write!(
747                    f,
748                    "cannot access extern static `{did}`",
749                    did = ty::tls::with(|tcx| tcx.def_path_str(did))
750                )
751            }
752        }
753    }
754}
755
756/// Error information for when the program exhausted the resources granted to it
757/// by the interpreter.
758#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ResourceExhaustionInfo {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                ResourceExhaustionInfo::StackFrameLimitReached =>
                    "StackFrameLimitReached",
                ResourceExhaustionInfo::MemoryExhausted => "MemoryExhausted",
                ResourceExhaustionInfo::AddressSpaceFull =>
                    "AddressSpaceFull",
                ResourceExhaustionInfo::Interrupted => "Interrupted",
            })
    }
}Debug)]
759pub enum ResourceExhaustionInfo {
760    /// The stack grew too big.
761    StackFrameLimitReached,
762    /// There is not enough memory (on the host) to perform an allocation.
763    MemoryExhausted,
764    /// The address space (of the target) is full.
765    AddressSpaceFull,
766    /// The compiler got an interrupt signal (a user ran out of patience).
767    Interrupted,
768}
769
770impl fmt::Display for ResourceExhaustionInfo {
771    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
772        use ResourceExhaustionInfo::*;
773        match self {
774            StackFrameLimitReached => {
775                f.write_fmt(format_args!("reached the configured maximum number of stack frames"))write!(f, "reached the configured maximum number of stack frames")
776            }
777            MemoryExhausted => {
778                f.write_fmt(format_args!("tried to allocate more memory than available to compiler"))write!(f, "tried to allocate more memory than available to compiler")
779            }
780            AddressSpaceFull => {
781                f.write_fmt(format_args!("there are no more free addresses in the address space"))write!(f, "there are no more free addresses in the address space")
782            }
783            Interrupted => f.write_fmt(format_args!("compilation was interrupted"))write!(f, "compilation was interrupted"),
784        }
785    }
786}
787
788/// A trait for machine-specific errors (or other "machine stop" conditions).
789pub trait MachineStopType: Any + fmt::Display + fmt::Debug + Send {
790    /// This error occurred during validation, inside a value at the given path.
791    fn with_validation_path(&mut self, _path: String) {}
792}
793
794impl dyn MachineStopType {
795    #[inline(always)]
796    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
797        let x: &dyn Any = self;
798        x.downcast_ref()
799    }
800}
801
802#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for InterpErrorKind<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            InterpErrorKind::UndefinedBehavior(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "UndefinedBehavior", &__self_0),
            InterpErrorKind::InvalidProgram(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "InvalidProgram", &__self_0),
            InterpErrorKind::Unsupported(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Unsupported", &__self_0),
            InterpErrorKind::ResourceExhaustion(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ResourceExhaustion", &__self_0),
            InterpErrorKind::MachineStop(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "MachineStop", &__self_0),
        }
    }
}Debug)]
803pub enum InterpErrorKind<'tcx> {
804    /// The program caused undefined behavior.
805    UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
806    /// The program was invalid (ill-typed, bad MIR, not sufficiently monomorphized, ...).
807    InvalidProgram(InvalidProgramInfo<'tcx>),
808    /// The program did something the interpreter does not support (some of these *might* be UB
809    /// but the interpreter is not sure).
810    Unsupported(UnsupportedOpInfo),
811    /// The program exhausted the interpreter's resources (stack/heap too big,
812    /// execution takes too long, ...).
813    ResourceExhaustion(ResourceExhaustionInfo),
814    /// Stop execution for a machine-controlled reason. This is never raised by
815    /// the core engine itself.
816    MachineStop(Box<dyn MachineStopType>),
817}
818
819impl<'tcx> fmt::Display for InterpErrorKind<'tcx> {
820    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
821        use InterpErrorKind::*;
822        match self {
823            Unsupported(msg) => f.write_fmt(format_args!("{0}", msg))write!(f, "{msg}"),
824            InvalidProgram(msg) => f.write_fmt(format_args!("{0}", msg))write!(f, "{msg}"),
825            UndefinedBehavior(msg) => f.write_fmt(format_args!("{0}", msg))write!(f, "{msg}"),
826            ResourceExhaustion(msg) => f.write_fmt(format_args!("{0}", msg))write!(f, "{msg}"),
827            MachineStop(msg) => f.write_fmt(format_args!("{0}", msg))write!(f, "{msg}"),
828        }
829    }
830}
831
832impl InterpErrorKind<'_> {
833    /// Some errors do string formatting even if the error is never printed.
834    /// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors,
835    /// so this method lets us detect them and `bug!` on unexpected errors.
836    pub fn formatted_string(&self) -> bool {
837        #[allow(non_exhaustive_omitted_patterns)] match self {
    InterpErrorKind::Unsupported(UnsupportedOpInfo::Unsupported(_)) |
        InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError {
        .. }) |
        InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) =>
        true,
    _ => false,
}matches!(
838            self,
839            InterpErrorKind::Unsupported(UnsupportedOpInfo::Unsupported(_))
840                | InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { .. })
841                | InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
842        )
843    }
844}
845
846// Macros for constructing / throwing `InterpErrorKind`
847#[macro_export]
848macro_rules! err_unsup {
849    ($($tt:tt)*) => {
850        $crate::mir::interpret::InterpErrorKind::Unsupported(
851            $crate::mir::interpret::UnsupportedOpInfo::$($tt)*
852        )
853    };
854}
855
856#[macro_export]
857macro_rules! err_unsup_format {
858    ($($tt:tt)*) => { $crate::err_unsup!(Unsupported(format!($($tt)*))) };
859}
860
861#[macro_export]
862macro_rules! err_inval {
863    ($($tt:tt)*) => {
864        $crate::mir::interpret::InterpErrorKind::InvalidProgram(
865            $crate::mir::interpret::InvalidProgramInfo::$($tt)*
866        )
867    };
868}
869
870#[macro_export]
871macro_rules! err_ub {
872    ($($tt:tt)*) => {
873        $crate::mir::interpret::InterpErrorKind::UndefinedBehavior(
874            $crate::mir::interpret::UndefinedBehaviorInfo::$($tt)*
875        )
876    };
877}
878
879#[macro_export]
880macro_rules! err_ub_format {
881    ($($tt:tt)*) => { $crate::err_ub!(Ub(format!($($tt)*))) };
882}
883
884#[macro_export]
885macro_rules! err_exhaust {
886    ($($tt:tt)*) => {
887        $crate::mir::interpret::InterpErrorKind::ResourceExhaustion(
888            $crate::mir::interpret::ResourceExhaustionInfo::$($tt)*
889        )
890    };
891}
892
893#[macro_export]
894macro_rules! err_machine_stop {
895    ($($tt:tt)*) => {
896        $crate::mir::interpret::InterpErrorKind::MachineStop(Box::new($($tt)*))
897    };
898}
899
900// In the `throw_*` macros, avoid `return` to make them work with `try {}`.
901#[macro_export]
902macro_rules! throw_unsup {
903    ($($tt:tt)*) => { do yeet $crate::err_unsup!($($tt)*) };
904}
905
906#[macro_export]
907macro_rules! throw_unsup_format {
908    ($($tt:tt)*) => { do yeet $crate::err_unsup_format!($($tt)*) };
909}
910
911#[macro_export]
912macro_rules! throw_inval {
913    ($($tt:tt)*) => { do yeet $crate::err_inval!($($tt)*) };
914}
915
916#[macro_export]
917macro_rules! throw_ub {
918    ($($tt:tt)*) => { do yeet $crate::err_ub!($($tt)*) };
919}
920
921#[macro_export]
922macro_rules! throw_ub_format {
923    ($($tt:tt)*) => { do yeet $crate::err_ub_format!($($tt)*) };
924}
925
926#[macro_export]
927macro_rules! throw_exhaust {
928    ($($tt:tt)*) => { do yeet $crate::err_exhaust!($($tt)*) };
929}
930
931#[macro_export]
932macro_rules! throw_machine_stop {
933    ($($tt:tt)*) => { do yeet $crate::err_machine_stop!($($tt)*) };
934}
935
936/// Guard type that panics on drop.
937#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Guard {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "Guard")
    }
}Debug)]
938struct Guard;
939
940impl Drop for Guard {
941    fn drop(&mut self) {
942        // We silence the guard if we are already panicking, to avoid double-panics.
943        if !std::thread::panicking() {
944            {
    ::core::panicking::panic_fmt(format_args!("an interpreter error got improperly discarded; use `discard_err()` if this is intentional"));
};panic!(
945                "an interpreter error got improperly discarded; use `discard_err()` if this is intentional"
946            );
947        }
948    }
949}
950
951/// The result type used by the interpreter. This is a newtype around `Result`
952/// to block access to operations like `ok()` that discard UB errors.
953///
954/// We also make things panic if this type is ever implicitly dropped.
955#[derive(#[automatically_derived]
impl<'tcx, T: ::core::fmt::Debug> ::core::fmt::Debug for InterpResult<'tcx, T>
    {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "InterpResult",
            "res", &self.res, "guard", &&self.guard)
    }
}Debug)]
956#[must_use]
957pub struct InterpResult<'tcx, T = ()> {
958    res: Result<T, InterpErrorInfo<'tcx>>,
959    guard: Guard,
960}
961
962impl<'tcx, T> ops::Try for InterpResult<'tcx, T> {
963    type Output = T;
964    type Residual = InterpResult<'tcx, convert::Infallible>;
965
966    #[inline]
967    fn from_output(output: Self::Output) -> Self {
968        InterpResult::new(Ok(output))
969    }
970
971    #[inline]
972    fn branch(self) -> ops::ControlFlow<Self::Residual, Self::Output> {
973        match self.disarm() {
974            Ok(v) => ops::ControlFlow::Continue(v),
975            Err(e) => ops::ControlFlow::Break(InterpResult::new(Err(e))),
976        }
977    }
978}
979
980impl<'tcx, T> ops::Residual<T> for InterpResult<'tcx, convert::Infallible> {
981    type TryType = InterpResult<'tcx, T>;
982}
983
984impl<'tcx, T> ops::FromResidual for InterpResult<'tcx, T> {
985    #[inline]
986    #[track_caller]
987    fn from_residual(residual: InterpResult<'tcx, convert::Infallible>) -> Self {
988        match residual.disarm() {
989            Err(e) => Self::new(Err(e)),
990        }
991    }
992}
993
994// Allow `yeet`ing `InterpError` in functions returning `InterpResult_`.
995impl<'tcx, T> ops::FromResidual<ops::Yeet<InterpErrorKind<'tcx>>> for InterpResult<'tcx, T> {
996    #[inline]
997    fn from_residual(ops::Yeet(e): ops::Yeet<InterpErrorKind<'tcx>>) -> Self {
998        Self::new(Err(e.into()))
999    }
1000}
1001
1002// Allow `?` on `Result<_, InterpError>` in functions returning `InterpResult_`.
1003// This is useful e.g. for `option.ok_or_else(|| err_ub!(...))`.
1004impl<'tcx, T, E: Into<InterpErrorInfo<'tcx>>> ops::FromResidual<Result<convert::Infallible, E>>
1005    for InterpResult<'tcx, T>
1006{
1007    #[inline]
1008    fn from_residual(residual: Result<convert::Infallible, E>) -> Self {
1009        match residual {
1010            Err(e) => Self::new(Err(e.into())),
1011        }
1012    }
1013}
1014
1015impl<'tcx, T, E: Into<InterpErrorInfo<'tcx>>> From<Result<T, E>> for InterpResult<'tcx, T> {
1016    #[inline]
1017    fn from(value: Result<T, E>) -> Self {
1018        Self::new(value.map_err(|e| e.into()))
1019    }
1020}
1021
1022impl<'tcx, T, V: FromIterator<T>> FromIterator<InterpResult<'tcx, T>> for InterpResult<'tcx, V> {
1023    fn from_iter<I: IntoIterator<Item = InterpResult<'tcx, T>>>(iter: I) -> Self {
1024        Self::new(iter.into_iter().map(|x| x.disarm()).collect())
1025    }
1026}
1027
1028impl<'tcx, T> InterpResult<'tcx, T> {
1029    #[inline(always)]
1030    fn new(res: Result<T, InterpErrorInfo<'tcx>>) -> Self {
1031        Self { res, guard: Guard }
1032    }
1033
1034    #[inline(always)]
1035    fn disarm(self) -> Result<T, InterpErrorInfo<'tcx>> {
1036        mem::forget(self.guard);
1037        self.res
1038    }
1039
1040    /// Discard the error information in this result. Only use this if ignoring Undefined Behavior is okay!
1041    #[inline]
1042    pub fn discard_err(self) -> Option<T> {
1043        self.disarm().ok()
1044    }
1045
1046    /// Look at the `Result` wrapped inside of this.
1047    /// Must only be used to report the error!
1048    #[inline]
1049    pub fn report_err(self) -> Result<T, InterpErrorInfo<'tcx>> {
1050        self.disarm()
1051    }
1052
1053    #[inline]
1054    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> InterpResult<'tcx, U> {
1055        InterpResult::new(self.disarm().map(f))
1056    }
1057
1058    #[inline]
1059    pub fn map_err_kind(
1060        self,
1061        f: impl FnOnce(InterpErrorKind<'tcx>) -> InterpErrorKind<'tcx>,
1062    ) -> InterpResult<'tcx, T> {
1063        InterpResult::new(self.disarm().map_err(|mut e| {
1064            e.0.kind = f(e.0.kind);
1065            e
1066        }))
1067    }
1068
1069    #[inline]
1070    pub fn inspect_err_info(self, f: impl FnOnce(&InterpErrorInfo<'tcx>)) -> InterpResult<'tcx, T> {
1071        InterpResult::new(self.disarm().inspect_err(f))
1072    }
1073
1074    #[inline]
1075    #[track_caller]
1076    pub fn unwrap(self) -> T {
1077        self.disarm().unwrap()
1078    }
1079
1080    #[inline]
1081    #[track_caller]
1082    pub fn unwrap_or_else(self, f: impl FnOnce(InterpErrorInfo<'tcx>) -> T) -> T {
1083        self.disarm().unwrap_or_else(f)
1084    }
1085
1086    #[inline]
1087    #[track_caller]
1088    pub fn expect(self, msg: &str) -> T {
1089        self.disarm().expect(msg)
1090    }
1091
1092    #[inline]
1093    pub fn and_then<U>(self, f: impl FnOnce(T) -> InterpResult<'tcx, U>) -> InterpResult<'tcx, U> {
1094        InterpResult::new(self.disarm().and_then(|t| f(t).disarm()))
1095    }
1096
1097    /// Returns success if both `self` and `other` succeed, while ensuring we don't
1098    /// accidentally drop an error.
1099    ///
1100    /// If both are an error, `self` will be reported.
1101    #[inline]
1102    pub fn and<U>(self, other: InterpResult<'tcx, U>) -> InterpResult<'tcx, (T, U)> {
1103        match self.disarm() {
1104            Ok(t) => interp_ok((t, other?)),
1105            Err(e) => {
1106                // Discard the other error.
1107                drop(other.disarm());
1108                // Return `self`.
1109                InterpResult::new(Err(e))
1110            }
1111        }
1112    }
1113}
1114
1115#[inline(always)]
1116pub fn interp_ok<'tcx, T>(x: T) -> InterpResult<'tcx, T> {
1117    InterpResult::new(Ok(x))
1118}