Skip to main content

rustc_const_eval/const_eval/
eval_queries.rs

1use std::sync::atomic::Ordering::Relaxed;
2
3use either::{Left, Right};
4use rustc_abi::{self as abi, BackendRepr};
5use rustc_hir::def::DefKind;
6use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo, ReportedErrorInfo};
7use rustc_middle::mir::{self, ConstAlloc, ConstValue};
8use rustc_middle::query::TyCtxtAt;
9use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout};
10use rustc_middle::ty::print::with_no_trimmed_paths;
11use rustc_middle::ty::{self, Ty, TyCtxt};
12use rustc_middle::{bug, throw_inval};
13use rustc_span::Span;
14use rustc_span::def_id::LocalDefId;
15use tracing::{debug, instrument, trace};
16
17use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine};
18use crate::const_eval::CheckAlignment;
19use crate::interpret::{
20    CtfeValidationMode, GlobalId, Immediate, InternError, InternKind, InterpCx, InterpErrorKind,
21    InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, ReturnContinuation, create_static_alloc,
22    intern_const_alloc_recursive, interp_ok, throw_exhaust,
23};
24use crate::{CTRL_C_RECEIVED, errors};
25
26fn setup_for_eval<'tcx>(
27    ecx: &mut CompileTimeInterpCx<'tcx>,
28    cid: GlobalId<'tcx>,
29    layout: TyAndLayout<'tcx>,
30) -> InterpResult<'tcx, (InternKind, MPlaceTy<'tcx>)> {
31    let tcx = *ecx.tcx;
32    if !(cid.promoted.is_some() ||
            #[allow(non_exhaustive_omitted_patterns)] match ecx.tcx.def_kind(cid.instance.def_id())
                {
                DefKind::Const { .. } | DefKind::Static { .. } |
                    DefKind::ConstParam | DefKind::AnonConst |
                    DefKind::InlineConst | DefKind::AssocConst { .. } => true,
                _ => false,
            }) {
    {
        ::core::panicking::panic_fmt(format_args!("Unexpected DefKind: {0:?}",
                ecx.tcx.def_kind(cid.instance.def_id())));
    }
};assert!(
33        cid.promoted.is_some()
34            || matches!(
35                ecx.tcx.def_kind(cid.instance.def_id()),
36                DefKind::Const { .. }
37                    | DefKind::Static { .. }
38                    | DefKind::ConstParam
39                    | DefKind::AnonConst
40                    | DefKind::InlineConst
41                    | DefKind::AssocConst { .. }
42            ),
43        "Unexpected DefKind: {:?}",
44        ecx.tcx.def_kind(cid.instance.def_id())
45    );
46    if !layout.is_sized() {
    ::core::panicking::panic("assertion failed: layout.is_sized()")
};assert!(layout.is_sized());
47
48    let intern_kind = if cid.promoted.is_some() {
49        InternKind::Promoted
50    } else {
51        match tcx.static_mutability(cid.instance.def_id()) {
52            Some(m) => InternKind::Static(m),
53            None => InternKind::Constant,
54        }
55    };
56
57    let return_place = if let InternKind::Static(_) = intern_kind {
58        create_static_alloc(ecx, cid.instance.def_id().expect_local(), layout)
59    } else {
60        ecx.allocate(layout, MemoryKind::Stack)
61    };
62
63    return_place.map(|ret| (intern_kind, ret))
64}
65
66#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("eval_body_using_ecx",
                                    "rustc_const_eval::const_eval::eval_queries",
                                    ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(66u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                    ::tracing_core::field::FieldSet::new(&["cid"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cid)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: InterpResult<'tcx, R> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let tcx = *ecx.tcx;
            let layout =
                ecx.layout_of(body.bound_return_ty().instantiate(tcx,
                            cid.instance.args))?;
            let (intern_kind, ret) = setup_for_eval(ecx, cid, layout)?;
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_const_eval/src/const_eval/eval_queries.rs:76",
                                    "rustc_const_eval::const_eval::eval_queries",
                                    ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(76u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                    ::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};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&format_args!("eval_body_using_ecx: pushing stack frame for global: {0}{1}",
                                                                {
                                                                    let _guard = NoTrimmedGuard::new();
                                                                    ecx.tcx.def_path_str(cid.instance.def_id())
                                                                },
                                                                cid.promoted.map_or_else(String::new,
                                                                    |p|
                                                                        ::alloc::__export::must_use({
                                                                                ::alloc::fmt::format(format_args!("::{0:?}", p))
                                                                            }))) as &dyn Value))])
                        });
                } else { ; }
            };
            ecx.push_stack_frame_raw(cid.instance, body, &ret.clone().into(),
                    ReturnContinuation::Stop { cleanup: false })?;
            ecx.push_stack_frame_done()?;
            while ecx.step()? {
                if CTRL_C_RECEIVED.load(Relaxed) {
                    do yeet ::rustc_middle::mir::interpret::InterpErrorKind::ResourceExhaustion(::rustc_middle::mir::interpret::ResourceExhaustionInfo::Interrupted);
                }
            }
            intern_and_validate(ecx, cid, intern_kind, ret)
        }
    }
}#[instrument(level = "trace", skip(ecx, body))]
67fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
68    ecx: &mut CompileTimeInterpCx<'tcx>,
69    cid: GlobalId<'tcx>,
70    body: &'tcx mir::Body<'tcx>,
71) -> InterpResult<'tcx, R> {
72    let tcx = *ecx.tcx;
73    let layout = ecx.layout_of(body.bound_return_ty().instantiate(tcx, cid.instance.args))?;
74    let (intern_kind, ret) = setup_for_eval(ecx, cid, layout)?;
75
76    trace!(
77        "eval_body_using_ecx: pushing stack frame for global: {}{}",
78        with_no_trimmed_paths!(ecx.tcx.def_path_str(cid.instance.def_id())),
79        cid.promoted.map_or_else(String::new, |p| format!("::{p:?}"))
80    );
81
82    // This can't use `init_stack_frame` since `body` is not a function,
83    // so computing its ABI would fail. It's also not worth it since there are no arguments to pass.
84    ecx.push_stack_frame_raw(
85        cid.instance,
86        body,
87        &ret.clone().into(),
88        ReturnContinuation::Stop { cleanup: false },
89    )?;
90    ecx.push_stack_frame_done()?;
91
92    // The main interpreter loop.
93    while ecx.step()? {
94        if CTRL_C_RECEIVED.load(Relaxed) {
95            throw_exhaust!(Interrupted);
96        }
97    }
98
99    intern_and_validate(ecx, cid, intern_kind, ret)
100}
101
102#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("eval_trivial_const_using_ecx",
                                    "rustc_const_eval::const_eval::eval_queries",
                                    ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(102u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                    ::tracing_core::field::FieldSet::new(&["cid", "val", "ty"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cid)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&val)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: InterpResult<'tcx, R> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let layout = ecx.layout_of(ty)?;
            let (intern_kind, return_place) =
                setup_for_eval(ecx, cid, layout)?;
            let opty = ecx.const_val_to_op(val, ty, Some(layout))?;
            ecx.copy_op(&opty, &return_place)?;
            intern_and_validate(ecx, cid, intern_kind, return_place)
        }
    }
}#[instrument(level = "trace", skip(ecx))]
103fn eval_trivial_const_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
104    ecx: &mut CompileTimeInterpCx<'tcx>,
105    cid: GlobalId<'tcx>,
106    val: ConstValue,
107    ty: Ty<'tcx>,
108) -> InterpResult<'tcx, R> {
109    let layout = ecx.layout_of(ty)?;
110    let (intern_kind, return_place) = setup_for_eval(ecx, cid, layout)?;
111
112    let opty = ecx.const_val_to_op(val, ty, Some(layout))?;
113    ecx.copy_op(&opty, &return_place)?;
114
115    intern_and_validate(ecx, cid, intern_kind, return_place)
116}
117
118fn intern_and_validate<'tcx, R: InterpretationResult<'tcx>>(
119    ecx: &mut CompileTimeInterpCx<'tcx>,
120    cid: GlobalId<'tcx>,
121    intern_kind: InternKind,
122    ret: MPlaceTy<'tcx>,
123) -> InterpResult<'tcx, R> {
124    // Intern the result
125    let intern_result = intern_const_alloc_recursive(ecx, intern_kind, &ret);
126
127    // Since evaluation had no errors, validate the resulting constant.
128    const_validate_mplace(ecx, &ret, cid)?;
129
130    // Only report this after validation, as validation produces much better diagnostics.
131    // FIXME: ensure validation always reports this and stop making interning care about it.
132
133    match intern_result {
134        Ok(()) => {}
135        Err(InternError::DanglingPointer) => {
136            do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(errors::DanglingPtrInFinal {
                        span: ecx.tcx.span,
                        kind: intern_kind,
                    }))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
137                ecx.tcx
138                    .dcx()
139                    .emit_err(errors::DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind }),
140            )));
141        }
142        Err(InternError::BadMutablePointer) => {
143            do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(errors::MutablePtrInFinal {
                        span: ecx.tcx.span,
                        kind: intern_kind,
                    }))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
144                ecx.tcx
145                    .dcx()
146                    .emit_err(errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind }),
147            )));
148        }
149        Err(InternError::ConstAllocNotGlobal) => {
150            do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(errors::ConstHeapPtrInFinal {
                        span: ecx.tcx.span,
                    }))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
151                ecx.tcx.dcx().emit_err(errors::ConstHeapPtrInFinal { span: ecx.tcx.span }),
152            )));
153        }
154        Err(InternError::PartialPointer) => {
155            do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(errors::PartialPtrInFinal {
                        span: ecx.tcx.span,
                        kind: intern_kind,
                    }))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
156                ecx.tcx
157                    .dcx()
158                    .emit_err(errors::PartialPtrInFinal { span: ecx.tcx.span, kind: intern_kind }),
159            )));
160        }
161    }
162
163    interp_ok(R::make_result(ret, ecx))
164}
165
166/// The `InterpCx` is only meant to be used to do field and index projections into constants for
167/// `simd_shuffle` and const patterns in match arms.
168///
169/// This should *not* be used to do any actual interpretation. In particular, alignment checks are
170/// turned off!
171///
172/// The function containing the `match` that is currently being analyzed may have generic bounds
173/// that inform us about the generic bounds of the constant. E.g., using an associated constant
174/// of a function's generic parameter will require knowledge about the bounds on the generic
175/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
176pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
177    tcx: TyCtxt<'tcx>,
178    root_span: Span,
179    typing_env: ty::TypingEnv<'tcx>,
180    can_access_mut_global: CanAccessMutGlobal,
181) -> CompileTimeInterpCx<'tcx> {
182    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_const_eval/src/const_eval/eval_queries.rs:182",
                        "rustc_const_eval::const_eval::eval_queries",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                        ::tracing_core::__macro_support::Option::Some(182u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("mk_eval_cx: {0:?}",
                                                    typing_env) as &dyn Value))])
            });
    } else { ; }
};debug!("mk_eval_cx: {:?}", typing_env);
183    InterpCx::new(
184        tcx,
185        root_span,
186        typing_env,
187        CompileTimeMachine::new(can_access_mut_global, CheckAlignment::No),
188    )
189}
190
191/// Create an interpreter context to inspect the given `ConstValue`.
192/// Returns both the context and an `OpTy` that represents the constant.
193pub fn mk_eval_cx_for_const_val<'tcx>(
194    tcx: TyCtxtAt<'tcx>,
195    typing_env: ty::TypingEnv<'tcx>,
196    val: mir::ConstValue,
197    ty: Ty<'tcx>,
198) -> Option<(CompileTimeInterpCx<'tcx>, OpTy<'tcx>)> {
199    let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, typing_env, CanAccessMutGlobal::No);
200    // FIXME: is it a problem to discard the error here?
201    let op = ecx.const_val_to_op(val, ty, None).discard_err()?;
202    Some((ecx, op))
203}
204
205/// This function converts an interpreter value into a MIR constant.
206///
207/// The `for_diagnostics` flag turns the usual rules for returning `ConstValue::Scalar` into a
208/// best-effort attempt. This is not okay for use in const-eval sine it breaks invariants rustc
209/// relies on, but it is okay for diagnostics which will just give up gracefully when they
210/// encounter an `Indirect` they cannot handle.
211#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("op_to_const",
                                    "rustc_const_eval::const_eval::eval_queries",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(211u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                    ::tracing_core::field::FieldSet::new(&["op",
                                                    "for_diagnostics"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&op)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&for_diagnostics as
                                                            &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: ConstValue = loop {};
            return __tracing_attr_fake_return;
        }
        {
            if op.layout.is_zst() { return ConstValue::ZeroSized; }
            let force_as_immediate =
                match op.layout.backend_repr {
                    BackendRepr::Scalar(abi::Scalar::Initialized { .. }) =>
                        true,
                    _ => false,
                };
            let immediate =
                if force_as_immediate {
                    match ecx.read_immediate(op).report_err() {
                        Ok(imm) => Right(imm),
                        Err(err) => {
                            if for_diagnostics {
                                op.as_mplace_or_imm()
                            } else {
                                {
                                    ::core::panicking::panic_fmt(format_args!("normalization works on validated constants: {0:?}",
                                            err));
                                }
                            }
                        }
                    }
                } else { op.as_mplace_or_imm() };
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_const_eval/src/const_eval/eval_queries.rs:254",
                                    "rustc_const_eval::const_eval::eval_queries",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(254u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                    ::tracing_core::field::FieldSet::new(&["immediate"],
                                        ::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};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&immediate)
                                                        as &dyn Value))])
                        });
                } else { ; }
            };
            match immediate {
                Left(ref mplace) => {
                    let (prov, offset) =
                        mplace.ptr().into_pointer_or_addr().unwrap().prov_and_relative_offset();
                    let alloc_id = prov.alloc_id();
                    ConstValue::Indirect { alloc_id, offset }
                }
                Right(imm) =>
                    match *imm {
                        Immediate::Scalar(x) => ConstValue::Scalar(x),
                        Immediate::ScalarPair(a, b) => {
                            {
                                use ::tracing::__macro_support::Callsite as _;
                                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                    {
                                        static META: ::tracing::Metadata<'static> =
                                            {
                                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_const_eval/src/const_eval/eval_queries.rs:267",
                                                    "rustc_const_eval::const_eval::eval_queries",
                                                    ::tracing::Level::DEBUG,
                                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                                    ::tracing_core::__macro_support::Option::Some(267u32),
                                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                                    ::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};
                                            let mut iter = __CALLSITE.metadata().fields().iter();
                                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                                ::tracing::__macro_support::Option::Some(&format_args!("ScalarPair(a: {0:?}, b: {1:?})",
                                                                                a, b) as &dyn Value))])
                                        });
                                } else { ; }
                            };
                            let pointee_ty =
                                imm.layout.ty.builtin_deref(false).unwrap();
                            if true {
                                if !#[allow(non_exhaustive_omitted_patterns)] match ecx.tcx.struct_tail_for_codegen(pointee_ty,
                                                    ecx.typing_env()).kind() {
                                            ty::Str | ty::Slice(..) => true,
                                            _ => false,
                                        } {
                                    {
                                        ::core::panicking::panic_fmt(format_args!("`ConstValue::Slice` is for slice-tailed types only, but got {0}",
                                                imm.layout.ty));
                                    }
                                };
                            };
                            let msg =
                                "`op_to_const` on an immediate scalar pair must only be used on slice references to the beginning of an actual allocation";
                            let ptr = a.to_pointer(ecx).expect(msg);
                            let (prov, offset) =
                                ptr.into_pointer_or_addr().expect(msg).prov_and_relative_offset();
                            let alloc_id = prov.alloc_id();
                            if !(offset == abi::Size::ZERO) {
                                { ::core::panicking::panic_display(&msg); }
                            };
                            let meta = b.to_target_usize(ecx).expect(msg);
                            ConstValue::Slice { alloc_id, meta }
                        }
                        Immediate::Uninit =>
                            ::rustc_middle::util::bug::bug_fmt(format_args!("`Uninit` is not a valid value for {0}",
                                    op.layout.ty)),
                    },
            }
        }
    }
}#[instrument(skip(ecx), level = "debug")]
212pub(super) fn op_to_const<'tcx>(
213    ecx: &CompileTimeInterpCx<'tcx>,
214    op: &OpTy<'tcx>,
215    for_diagnostics: bool,
216) -> ConstValue {
217    // Handle ZST consistently and early.
218    if op.layout.is_zst() {
219        return ConstValue::ZeroSized;
220    }
221
222    // All scalar types should be stored as `ConstValue::Scalar`. This is needed to make
223    // `ConstValue::try_to_scalar` efficient; we want that to work for *all* constants of scalar
224    // type (it's used throughout the compiler and having it work just on literals is not enough)
225    // and we want it to be fast (i.e., don't go to an `Allocation` and reconstruct the `Scalar`
226    // from its byte-serialized form).
227    let force_as_immediate = match op.layout.backend_repr {
228        BackendRepr::Scalar(abi::Scalar::Initialized { .. }) => true,
229        // We don't *force* `ConstValue::Slice` for `ScalarPair`. This has the advantage that if the
230        // input `op` is a place, then turning it into a `ConstValue` and back into a `OpTy` will
231        // not have to generate any duplicate allocations (we preserve the original `AllocId` in
232        // `ConstValue::Indirect`). It means accessing the contents of a slice can be slow (since
233        // they can be stored as `ConstValue::Indirect`), but that's not relevant since we barely
234        // ever have to do this. (`try_get_slice_bytes_for_diagnostics` exists to provide this
235        // functionality.)
236        _ => false,
237    };
238    let immediate = if force_as_immediate {
239        match ecx.read_immediate(op).report_err() {
240            Ok(imm) => Right(imm),
241            Err(err) => {
242                if for_diagnostics {
243                    // This discard the error, but for diagnostics that's okay.
244                    op.as_mplace_or_imm()
245                } else {
246                    panic!("normalization works on validated constants: {err:?}")
247                }
248            }
249        }
250    } else {
251        op.as_mplace_or_imm()
252    };
253
254    debug!(?immediate);
255
256    match immediate {
257        Left(ref mplace) => {
258            let (prov, offset) =
259                mplace.ptr().into_pointer_or_addr().unwrap().prov_and_relative_offset();
260            let alloc_id = prov.alloc_id();
261            ConstValue::Indirect { alloc_id, offset }
262        }
263        // see comment on `let force_as_immediate` above
264        Right(imm) => match *imm {
265            Immediate::Scalar(x) => ConstValue::Scalar(x),
266            Immediate::ScalarPair(a, b) => {
267                debug!("ScalarPair(a: {:?}, b: {:?})", a, b);
268                // This codepath solely exists for `valtree_to_const_value` to not need to generate
269                // a `ConstValue::Indirect` for wide references, so it is tightly restricted to just
270                // that case.
271                let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs
272                debug_assert!(
273                    matches!(
274                        ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(),
275                        ty::Str | ty::Slice(..),
276                    ),
277                    "`ConstValue::Slice` is for slice-tailed types only, but got {}",
278                    imm.layout.ty,
279                );
280                let msg = "`op_to_const` on an immediate scalar pair must only be used on slice references to the beginning of an actual allocation";
281                let ptr = a.to_pointer(ecx).expect(msg);
282                let (prov, offset) =
283                    ptr.into_pointer_or_addr().expect(msg).prov_and_relative_offset();
284                let alloc_id = prov.alloc_id();
285                assert!(offset == abi::Size::ZERO, "{}", msg);
286                let meta = b.to_target_usize(ecx).expect(msg);
287                ConstValue::Slice { alloc_id, meta }
288            }
289            Immediate::Uninit => bug!("`Uninit` is not a valid value for {}", op.layout.ty),
290        },
291    }
292}
293
294x;#[instrument(skip(tcx), level = "debug", ret)]
295pub(crate) fn turn_into_const_value<'tcx>(
296    tcx: TyCtxt<'tcx>,
297    constant: ConstAlloc<'tcx>,
298    key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
299) -> ConstValue {
300    let cid = key.value;
301    let def_id = cid.instance.def.def_id();
302    let is_static = tcx.is_static(def_id);
303    // This is just accessing an already computed constant, so no need to check alignment here.
304    let ecx = mk_eval_cx_to_read_const_val(
305        tcx,
306        tcx.def_span(key.value.instance.def_id()),
307        key.typing_env,
308        CanAccessMutGlobal::from(is_static),
309    );
310
311    let mplace = ecx.raw_const_to_mplace(constant).expect(
312        "can only fail if layout computation failed, \
313        which should have given a good error before ever invoking this function",
314    );
315    assert!(
316        !is_static || cid.promoted.is_some(),
317        "the `eval_to_const_value_raw` query should not be used for statics, use `eval_to_allocation` instead"
318    );
319
320    // Turn this into a proper constant.
321    op_to_const(&ecx, &mplace.into(), /* for diagnostics */ false)
322}
323
324#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("eval_to_const_value_raw_provider",
                                    "rustc_const_eval::const_eval::eval_queries",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(324u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                    ::tracing_core::field::FieldSet::new(&["key"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&key)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return:
                    ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> =
                loop {};
            return __tracing_attr_fake_return;
        }
        {
            if let Some((value, _ty)) =
                    tcx.trivial_const(key.value.instance.def_id()) {
                return Ok(value);
            }
            tcx.eval_to_allocation_raw(key).map(|val|
                    turn_into_const_value(tcx, val, key))
        }
    }
}#[instrument(skip(tcx), level = "debug")]
325pub fn eval_to_const_value_raw_provider<'tcx>(
326    tcx: TyCtxt<'tcx>,
327    key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
328) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
329    if let Some((value, _ty)) = tcx.trivial_const(key.value.instance.def_id()) {
330        return Ok(value);
331    }
332    tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key))
333}
334
335#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("eval_static_initializer_provider",
                                    "rustc_const_eval::const_eval::eval_queries",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(335u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                    ::tracing_core::field::FieldSet::new(&["def_id"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return:
                    ::rustc_middle::mir::interpret::EvalStaticInitializerRawResult<'tcx> =
                loop {};
            return __tracing_attr_fake_return;
        }
        {
            if !tcx.is_static(def_id.to_def_id()) {
                ::core::panicking::panic("assertion failed: tcx.is_static(def_id.to_def_id())")
            };
            let instance = ty::Instance::mono(tcx, def_id.to_def_id());
            let cid =
                rustc_middle::mir::interpret::GlobalId {
                    instance,
                    promoted: None,
                };
            eval_in_interpreter(tcx, cid,
                ty::TypingEnv::fully_monomorphized())
        }
    }
}#[instrument(skip(tcx), level = "debug")]
336pub fn eval_static_initializer_provider<'tcx>(
337    tcx: TyCtxt<'tcx>,
338    def_id: LocalDefId,
339) -> ::rustc_middle::mir::interpret::EvalStaticInitializerRawResult<'tcx> {
340    assert!(tcx.is_static(def_id.to_def_id()));
341
342    let instance = ty::Instance::mono(tcx, def_id.to_def_id());
343    let cid = rustc_middle::mir::interpret::GlobalId { instance, promoted: None };
344    eval_in_interpreter(tcx, cid, ty::TypingEnv::fully_monomorphized())
345}
346
347pub trait InterpretationResult<'tcx> {
348    /// This function takes the place where the result of the evaluation is stored
349    /// and prepares it for returning it in the appropriate format needed by the specific
350    /// evaluation query.
351    fn make_result(
352        mplace: MPlaceTy<'tcx>,
353        ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
354    ) -> Self;
355}
356
357impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> {
358    fn make_result(
359        mplace: MPlaceTy<'tcx>,
360        _ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
361    ) -> Self {
362        ConstAlloc { alloc_id: mplace.ptr().provenance.unwrap().alloc_id(), ty: mplace.layout.ty }
363    }
364}
365
366#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("eval_to_allocation_raw_provider",
                                    "rustc_const_eval::const_eval::eval_queries",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(366u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                    ::tracing_core::field::FieldSet::new(&["key"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&key)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return:
                    ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> =
                loop {};
            return __tracing_attr_fake_return;
        }
        {
            if !(key.value.promoted.is_some() ||
                        !tcx.is_static(key.value.instance.def_id())) {
                ::core::panicking::panic("assertion failed: key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id())")
            };
            if true {
                match (&key.typing_env.typing_mode,
                        &ty::TypingMode::PostAnalysis) {
                    (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);
                        }
                    }
                };
            };
            if true {
                let instance =
                    {
                        let _guard = NoTrimmedGuard::new();
                        key.value.instance.to_string()
                    };
                {
                    use ::tracing::__macro_support::Callsite as _;
                    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                        {
                            static META: ::tracing::Metadata<'static> =
                                {
                                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_const_eval/src/const_eval/eval_queries.rs:384",
                                        "rustc_const_eval::const_eval::eval_queries",
                                        ::tracing::Level::TRACE,
                                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                        ::tracing_core::__macro_support::Option::Some(384u32),
                                        ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                        ::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};
                                let mut iter = __CALLSITE.metadata().fields().iter();
                                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&format_args!("const eval: {0:?} ({1})",
                                                                    key, instance) as &dyn Value))])
                            });
                    } else { ; }
                };
            }
            eval_in_interpreter(tcx, key.value, key.typing_env)
        }
    }
}#[instrument(skip(tcx), level = "debug")]
367pub fn eval_to_allocation_raw_provider<'tcx>(
368    tcx: TyCtxt<'tcx>,
369    key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
370) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
371    // This shouldn't be used for statics, since statics are conceptually places,
372    // not values -- so what we do here could break pointer identity.
373    assert!(key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id()));
374    // Const eval always happens in PostAnalysis mode . See the comment in
375    // `InterpCx::new` for more details.
376    debug_assert_eq!(key.typing_env.typing_mode, ty::TypingMode::PostAnalysis);
377    if cfg!(debug_assertions) {
378        // Make sure we format the instance even if we do not print it.
379        // This serves as a regression test against an ICE on printing.
380        // The next two lines concatenated contain some discussion:
381        // https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/
382        // subject/anon_const_instance_printing/near/135980032
383        let instance = with_no_trimmed_paths!(key.value.instance.to_string());
384        trace!("const eval: {:?} ({})", key, instance);
385    }
386
387    eval_in_interpreter(tcx, key.value, key.typing_env)
388}
389
390fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
391    tcx: TyCtxt<'tcx>,
392    cid: GlobalId<'tcx>,
393    typing_env: ty::TypingEnv<'tcx>,
394) -> Result<R, ErrorHandled> {
395    let def = cid.instance.def.def_id();
396    // `type const` don't have bodys
397    if true {
    if !!tcx.is_type_const(def) {
        {
            ::core::panicking::panic_fmt(format_args!("CTFE tried to evaluate type-const: {0:?}",
                    def));
        }
    };
};debug_assert!(!tcx.is_type_const(def), "CTFE tried to evaluate type-const: {:?}", def);
398
399    let is_static = tcx.is_static(def);
400    let mut ecx = InterpCx::new(
401        tcx,
402        tcx.def_span(def),
403        typing_env,
404        // Statics (and promoteds inside statics) may access mutable global memory, because unlike consts
405        // they do not have to behave "as if" they were evaluated at runtime.
406        // For consts however we want to ensure they behave "as if" they were evaluated at runtime,
407        // so we have to reject reading mutable global memory.
408        CompileTimeMachine::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error),
409    );
410
411    let result = if let Some((value, ty)) = tcx.trivial_const(def) {
412        eval_trivial_const_using_ecx(&mut ecx, cid, value, ty)
413    } else {
414        ecx.load_mir(cid.instance.def, cid.promoted)
415            .and_then(|body| eval_body_using_ecx(&mut ecx, cid, body))
416    };
417    result.report_err().map_err(|error| report_eval_error(&ecx, cid, error))
418}
419
420#[inline(always)]
421fn const_validate_mplace<'tcx>(
422    ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
423    mplace: &MPlaceTy<'tcx>,
424    cid: GlobalId<'tcx>,
425) -> Result<(), ErrorHandled> {
426    let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
427    let mut ref_tracking = RefTracking::new(mplace.clone(), mplace.layout.ty);
428    let mut inner = false;
429    while let Some((mplace, path)) = ref_tracking.next() {
430        let mode = match ecx.tcx.static_mutability(cid.instance.def_id()) {
431            _ if cid.promoted.is_some() => CtfeValidationMode::Promoted,
432            Some(mutbl) => CtfeValidationMode::Static { mutbl }, // a `static`
433            None => {
434                // This is a normal `const` (not promoted).
435                // The outermost allocation is always only copied, so having `UnsafeCell` in there
436                // is okay despite them being in immutable memory.
437                CtfeValidationMode::Const { allow_immutable_unsafe_cell: !inner }
438            }
439        };
440        ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)
441            .report_err()
442            // Instead of just reporting the `InterpError` via the usual machinery, we give a more targeted
443            // error about the validation failure.
444            .map_err(|error| report_validation_error(&ecx, cid, error, alloc_id))?;
445        inner = true;
446    }
447
448    Ok(())
449}
450
451#[inline(never)]
452fn report_eval_error<'tcx>(
453    ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
454    cid: GlobalId<'tcx>,
455    error: InterpErrorInfo<'tcx>,
456) -> ErrorHandled {
457    let (error, backtrace) = error.into_parts();
458    backtrace.print_backtrace();
459
460    super::report(ecx, error, |diag, span, frames| {
461        let num_frames = frames.len();
462        diag.span_label(
463            span,
464            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("evaluation of `{0}` failed {1}",
                {
                    let _guard = NoTrimmedGuard::new();
                    cid.instance.to_string()
                }, if num_frames == 0 { "here" } else { "inside this call" }))
    })format!(
465                "evaluation of `{instance}` failed {where_}",
466                instance = with_no_trimmed_paths!(cid.instance.to_string()),
467                where_ = if num_frames == 0 { "here" } else { "inside this call" },
468            ),
469        );
470        for frame in frames {
471            diag.subdiagnostic(frame);
472        }
473    })
474}
475
476#[inline(never)]
477fn report_validation_error<'tcx>(
478    ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
479    cid: GlobalId<'tcx>,
480    error: InterpErrorInfo<'tcx>,
481    alloc_id: AllocId,
482) -> ErrorHandled {
483    if !#[allow(non_exhaustive_omitted_patterns)] match error.kind() {
    InterpErrorKind::UndefinedBehavior(_) => true,
    _ => false,
}matches!(error.kind(), InterpErrorKind::UndefinedBehavior(_)) {
484        // Some other error happened during validation, e.g. an unsupported operation.
485        return report_eval_error(ecx, cid, error);
486    }
487
488    let (error, backtrace) = error.into_parts();
489    backtrace.print_backtrace();
490
491    let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id);
492    let info = ecx.get_alloc_info(alloc_id);
493    let raw_bytes =
494        errors::RawBytesNote { size: info.size.bytes(), align: info.align.bytes(), bytes };
495
496    crate::const_eval::report(ecx, error, move |diag, span, frames| {
497        diag.span_label(span, "it is undefined behavior to use this value");
498        diag.note("the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.");
499        if !frames.is_empty() {
    ::core::panicking::panic("assertion failed: frames.is_empty()")
};assert!(frames.is_empty()); // we just report validation errors for the final const here
500        diag.subdiagnostic(raw_bytes);
501    })
502}