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).skip_norm_wip())?;
            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:77",
                                    "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(77u32),
                                    ::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 =
74        ecx.layout_of(body.bound_return_ty().instantiate(tcx, cid.instance.args).skip_norm_wip())?;
75    let (intern_kind, ret) = setup_for_eval(ecx, cid, layout)?;
76
77    trace!(
78        "eval_body_using_ecx: pushing stack frame for global: {}{}",
79        with_no_trimmed_paths!(ecx.tcx.def_path_str(cid.instance.def_id())),
80        cid.promoted.map_or_else(String::new, |p| format!("::{p:?}"))
81    );
82
83    // This can't use `init_stack_frame` since `body` is not a function,
84    // so computing its ABI would fail. It's also not worth it since there are no arguments to pass.
85    ecx.push_stack_frame_raw(
86        cid.instance,
87        body,
88        &ret.clone().into(),
89        ReturnContinuation::Stop { cleanup: false },
90    )?;
91    ecx.push_stack_frame_done()?;
92
93    // The main interpreter loop.
94    while ecx.step()? {
95        if CTRL_C_RECEIVED.load(Relaxed) {
96            throw_exhaust!(Interrupted);
97        }
98    }
99
100    intern_and_validate(ecx, cid, intern_kind, ret)
101}
102
103#[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(103u32),
                                    ::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))]
104fn eval_trivial_const_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
105    ecx: &mut CompileTimeInterpCx<'tcx>,
106    cid: GlobalId<'tcx>,
107    val: ConstValue,
108    ty: Ty<'tcx>,
109) -> InterpResult<'tcx, R> {
110    let layout = ecx.layout_of(ty)?;
111    let (intern_kind, return_place) = setup_for_eval(ecx, cid, layout)?;
112
113    let opty = ecx.const_val_to_op(val, ty, Some(layout))?;
114    ecx.copy_op(&opty, &return_place)?;
115
116    intern_and_validate(ecx, cid, intern_kind, return_place)
117}
118
119fn intern_and_validate<'tcx, R: InterpretationResult<'tcx>>(
120    ecx: &mut CompileTimeInterpCx<'tcx>,
121    cid: GlobalId<'tcx>,
122    intern_kind: InternKind,
123    ret: MPlaceTy<'tcx>,
124) -> InterpResult<'tcx, R> {
125    // Intern the result
126    let intern_result = intern_const_alloc_recursive(ecx, intern_kind, &ret);
127
128    // Since evaluation had no errors, validate the resulting constant.
129    const_validate_mplace(ecx, &ret, cid)?;
130
131    // Only report this after validation, as validation produces much better diagnostics.
132    // FIXME: ensure validation always reports this and stop making interning care about it.
133
134    match intern_result {
135        Ok(()) => {}
136        Err(InternError::DanglingPointer) => {
137            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(
138                ecx.tcx
139                    .dcx()
140                    .emit_err(errors::DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind }),
141            )));
142        }
143        Err(InternError::BadMutablePointer) => {
144            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(
145                ecx.tcx
146                    .dcx()
147                    .emit_err(errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind }),
148            )));
149        }
150        Err(InternError::ConstAllocNotGlobal) => {
151            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(
152                ecx.tcx.dcx().emit_err(errors::ConstHeapPtrInFinal { span: ecx.tcx.span }),
153            )));
154        }
155        Err(InternError::PartialPointer) => {
156            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(
157                ecx.tcx
158                    .dcx()
159                    .emit_err(errors::PartialPtrInFinal { span: ecx.tcx.span, kind: intern_kind }),
160            )));
161        }
162    }
163
164    interp_ok(R::make_result(ret, ecx))
165}
166
167/// The `InterpCx` is only meant to be used to do field and index projections into constants for
168/// `simd_shuffle` and const patterns in match arms.
169///
170/// This should *not* be used to do any actual interpretation. In particular, alignment checks are
171/// turned off!
172///
173/// The function containing the `match` that is currently being analyzed may have generic bounds
174/// that inform us about the generic bounds of the constant. E.g., using an associated constant
175/// of a function's generic parameter will require knowledge about the bounds on the generic
176/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
177pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
178    tcx: TyCtxt<'tcx>,
179    root_span: Span,
180    typing_env: ty::TypingEnv<'tcx>,
181    can_access_mut_global: CanAccessMutGlobal,
182) -> CompileTimeInterpCx<'tcx> {
183    {
    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:183",
                        "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(183u32),
                        ::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);
184    InterpCx::new(
185        tcx,
186        root_span,
187        typing_env,
188        CompileTimeMachine::new(can_access_mut_global, CheckAlignment::No),
189    )
190}
191
192/// Create an interpreter context to inspect the given `ConstValue`.
193/// Returns both the context and an `OpTy` that represents the constant.
194pub fn mk_eval_cx_for_const_val<'tcx>(
195    tcx: TyCtxtAt<'tcx>,
196    typing_env: ty::TypingEnv<'tcx>,
197    val: mir::ConstValue,
198    ty: Ty<'tcx>,
199) -> Option<(CompileTimeInterpCx<'tcx>, OpTy<'tcx>)> {
200    let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, typing_env, CanAccessMutGlobal::No);
201    // FIXME: is it a problem to discard the error here?
202    let op = ecx.const_val_to_op(val, ty, None).discard_err()?;
203    Some((ecx, op))
204}
205
206/// This function converts an interpreter value into a MIR constant.
207///
208/// The `for_diagnostics` flag turns the usual rules for returning `ConstValue::Scalar` into a
209/// best-effort attempt. This is not okay for use in const-eval sine it breaks invariants rustc
210/// relies on, but it is okay for diagnostics which will just give up gracefully when they
211/// encounter an `Indirect` they cannot handle.
212#[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(212u32),
                                    ::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:255",
                                    "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(255u32),
                                    ::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:268",
                                                    "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(268u32),
                                                    ::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")]
213pub(super) fn op_to_const<'tcx>(
214    ecx: &CompileTimeInterpCx<'tcx>,
215    op: &OpTy<'tcx>,
216    for_diagnostics: bool,
217) -> ConstValue {
218    // Handle ZST consistently and early.
219    if op.layout.is_zst() {
220        return ConstValue::ZeroSized;
221    }
222
223    // All scalar types should be stored as `ConstValue::Scalar`. This is needed to make
224    // `ConstValue::try_to_scalar` efficient; we want that to work for *all* constants of scalar
225    // type (it's used throughout the compiler and having it work just on literals is not enough)
226    // and we want it to be fast (i.e., don't go to an `Allocation` and reconstruct the `Scalar`
227    // from its byte-serialized form).
228    let force_as_immediate = match op.layout.backend_repr {
229        BackendRepr::Scalar(abi::Scalar::Initialized { .. }) => true,
230        // We don't *force* `ConstValue::Slice` for `ScalarPair`. This has the advantage that if the
231        // input `op` is a place, then turning it into a `ConstValue` and back into a `OpTy` will
232        // not have to generate any duplicate allocations (we preserve the original `AllocId` in
233        // `ConstValue::Indirect`). It means accessing the contents of a slice can be slow (since
234        // they can be stored as `ConstValue::Indirect`), but that's not relevant since we barely
235        // ever have to do this. (`try_get_slice_bytes_for_diagnostics` exists to provide this
236        // functionality.)
237        _ => false,
238    };
239    let immediate = if force_as_immediate {
240        match ecx.read_immediate(op).report_err() {
241            Ok(imm) => Right(imm),
242            Err(err) => {
243                if for_diagnostics {
244                    // This discard the error, but for diagnostics that's okay.
245                    op.as_mplace_or_imm()
246                } else {
247                    panic!("normalization works on validated constants: {err:?}")
248                }
249            }
250        }
251    } else {
252        op.as_mplace_or_imm()
253    };
254
255    debug!(?immediate);
256
257    match immediate {
258        Left(ref mplace) => {
259            let (prov, offset) =
260                mplace.ptr().into_pointer_or_addr().unwrap().prov_and_relative_offset();
261            let alloc_id = prov.alloc_id();
262            ConstValue::Indirect { alloc_id, offset }
263        }
264        // see comment on `let force_as_immediate` above
265        Right(imm) => match *imm {
266            Immediate::Scalar(x) => ConstValue::Scalar(x),
267            Immediate::ScalarPair(a, b) => {
268                debug!("ScalarPair(a: {:?}, b: {:?})", a, b);
269                // This codepath solely exists for `valtree_to_const_value` to not need to generate
270                // a `ConstValue::Indirect` for wide references, so it is tightly restricted to just
271                // that case.
272                let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs
273                debug_assert!(
274                    matches!(
275                        ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(),
276                        ty::Str | ty::Slice(..),
277                    ),
278                    "`ConstValue::Slice` is for slice-tailed types only, but got {}",
279                    imm.layout.ty,
280                );
281                let msg = "`op_to_const` on an immediate scalar pair must only be used on slice references to the beginning of an actual allocation";
282                let ptr = a.to_pointer(ecx).expect(msg);
283                let (prov, offset) =
284                    ptr.into_pointer_or_addr().expect(msg).prov_and_relative_offset();
285                let alloc_id = prov.alloc_id();
286                assert!(offset == abi::Size::ZERO, "{}", msg);
287                let meta = b.to_target_usize(ecx).expect(msg);
288                ConstValue::Slice { alloc_id, meta }
289            }
290            Immediate::Uninit => bug!("`Uninit` is not a valid value for {}", op.layout.ty),
291        },
292    }
293}
294
295x;#[instrument(skip(tcx), level = "debug", ret)]
296pub(crate) fn turn_into_const_value<'tcx>(
297    tcx: TyCtxt<'tcx>,
298    constant: ConstAlloc<'tcx>,
299    key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
300) -> ConstValue {
301    let cid = key.value;
302    let def_id = cid.instance.def.def_id();
303    let is_static = tcx.is_static(def_id);
304    // This is just accessing an already computed constant, so no need to check alignment here.
305    let ecx = mk_eval_cx_to_read_const_val(
306        tcx,
307        tcx.def_span(key.value.instance.def_id()),
308        key.typing_env,
309        CanAccessMutGlobal::from(is_static),
310    );
311
312    let mplace = ecx.raw_const_to_mplace(constant).expect(
313        "can only fail if layout computation failed, \
314        which should have given a good error before ever invoking this function",
315    );
316    assert!(
317        !is_static || cid.promoted.is_some(),
318        "the `eval_to_const_value_raw` query should not be used for statics, use `eval_to_allocation` instead"
319    );
320
321    // Turn this into a proper constant.
322    op_to_const(&ecx, &mplace.into(), /* for diagnostics */ false)
323}
324
325#[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(325u32),
                                    ::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")]
326pub fn eval_to_const_value_raw_provider<'tcx>(
327    tcx: TyCtxt<'tcx>,
328    key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
329) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
330    if let Some((value, _ty)) = tcx.trivial_const(key.value.instance.def_id()) {
331        return Ok(value);
332    }
333    tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key))
334}
335
336#[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(336u32),
                                    ::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")]
337pub fn eval_static_initializer_provider<'tcx>(
338    tcx: TyCtxt<'tcx>,
339    def_id: LocalDefId,
340) -> ::rustc_middle::mir::interpret::EvalStaticInitializerRawResult<'tcx> {
341    assert!(tcx.is_static(def_id.to_def_id()));
342
343    let instance = ty::Instance::mono(tcx, def_id.to_def_id());
344    let cid = rustc_middle::mir::interpret::GlobalId { instance, promoted: None };
345    eval_in_interpreter(tcx, cid, ty::TypingEnv::fully_monomorphized())
346}
347
348pub trait InterpretationResult<'tcx> {
349    /// This function takes the place where the result of the evaluation is stored
350    /// and prepares it for returning it in the appropriate format needed by the specific
351    /// evaluation query.
352    fn make_result(
353        mplace: MPlaceTy<'tcx>,
354        ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
355    ) -> Self;
356}
357
358impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> {
359    fn make_result(
360        mplace: MPlaceTy<'tcx>,
361        _ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
362    ) -> Self {
363        ConstAlloc { alloc_id: mplace.ptr().provenance.unwrap().alloc_id(), ty: mplace.layout.ty }
364    }
365}
366
367#[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(367u32),
                                    ::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 => {}
                    ty::TypingMode::Coherence | ty::TypingMode::Analysis { .. }
                        | ty::TypingMode::Borrowck { .. } |
                        ty::TypingMode::PostBorrowckAnalysis { .. } => {
                        ::rustc_middle::util::bug::bug_fmt(format_args!("Const eval should always happens in PostAnalysis mode. See the comment in `InterpCx::new` for more details."))
                    }
                }
                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:395",
                                        "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(395u32),
                                        ::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")]
368pub fn eval_to_allocation_raw_provider<'tcx>(
369    tcx: TyCtxt<'tcx>,
370    key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
371) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
372    // This shouldn't be used for statics, since statics are conceptually places,
373    // not values -- so what we do here could break pointer identity.
374    assert!(key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id()));
375
376    if cfg!(debug_assertions) {
377        match key.typing_env.typing_mode() {
378            ty::TypingMode::PostAnalysis => {}
379            ty::TypingMode::Coherence
380            | ty::TypingMode::Analysis { .. }
381            | ty::TypingMode::Borrowck { .. }
382            | ty::TypingMode::PostBorrowckAnalysis { .. } => {
383                bug!(
384                    "Const eval should always happens in PostAnalysis mode. See the comment in `InterpCx::new` for more details."
385                )
386            }
387        }
388
389        // Make sure we format the instance even if we do not print it.
390        // This serves as a regression test against an ICE on printing.
391        // The next two lines concatenated contain some discussion:
392        // https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/
393        // subject/anon_const_instance_printing/near/135980032
394        let instance = with_no_trimmed_paths!(key.value.instance.to_string());
395        trace!("const eval: {:?} ({})", key, instance);
396    }
397
398    eval_in_interpreter(tcx, key.value, key.typing_env)
399}
400
401fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
402    tcx: TyCtxt<'tcx>,
403    cid: GlobalId<'tcx>,
404    typing_env: ty::TypingEnv<'tcx>,
405) -> Result<R, ErrorHandled> {
406    let def = cid.instance.def.def_id();
407    // `type const` don't have bodys
408    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);
409
410    let is_static = tcx.is_static(def);
411    let mut ecx = InterpCx::new(
412        tcx,
413        tcx.def_span(def),
414        typing_env,
415        // Statics (and promoteds inside statics) may access mutable global memory, because unlike consts
416        // they do not have to behave "as if" they were evaluated at runtime.
417        // For consts however we want to ensure they behave "as if" they were evaluated at runtime,
418        // so we have to reject reading mutable global memory.
419        CompileTimeMachine::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error),
420    );
421
422    let result = if let Some((value, ty)) = tcx.trivial_const(def) {
423        eval_trivial_const_using_ecx(&mut ecx, cid, value, ty)
424    } else {
425        ecx.load_mir(cid.instance.def, cid.promoted)
426            .and_then(|body| eval_body_using_ecx(&mut ecx, cid, body))
427    };
428    result.report_err().map_err(|error| report_eval_error(&ecx, cid, error))
429}
430
431#[inline(always)]
432fn const_validate_mplace<'tcx>(
433    ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
434    mplace: &MPlaceTy<'tcx>,
435    cid: GlobalId<'tcx>,
436) -> Result<(), ErrorHandled> {
437    let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
438    let mut ref_tracking = RefTracking::new(mplace.clone(), mplace.layout.ty);
439    let mut inner = false;
440    while let Some((mplace, path)) = ref_tracking.next() {
441        let mode = match ecx.tcx.static_mutability(cid.instance.def_id()) {
442            _ if cid.promoted.is_some() => CtfeValidationMode::Promoted,
443            Some(mutbl) => CtfeValidationMode::Static { mutbl }, // a `static`
444            None => {
445                // This is a normal `const` (not promoted).
446                // The outermost allocation is always only copied, so having `UnsafeCell` in there
447                // is okay despite them being in immutable memory.
448                CtfeValidationMode::Const { allow_immutable_unsafe_cell: !inner }
449            }
450        };
451        ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)
452            .report_err()
453            // Instead of just reporting the `InterpError` via the usual machinery, we give a more targeted
454            // error about the validation failure.
455            .map_err(|error| report_validation_error(&ecx, cid, error, alloc_id))?;
456        inner = true;
457    }
458
459    Ok(())
460}
461
462#[inline(never)]
463fn report_eval_error<'tcx>(
464    ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
465    cid: GlobalId<'tcx>,
466    error: InterpErrorInfo<'tcx>,
467) -> ErrorHandled {
468    let (error, backtrace) = error.into_parts();
469    backtrace.print_backtrace();
470
471    super::report(ecx, error, |diag, span, frames| {
472        let num_frames = frames.len();
473        diag.span_label(
474            span,
475            ::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!(
476                "evaluation of `{instance}` failed {where_}",
477                instance = with_no_trimmed_paths!(cid.instance.to_string()),
478                where_ = if num_frames == 0 { "here" } else { "inside this call" },
479            ),
480        );
481        for frame in frames {
482            diag.subdiagnostic(frame);
483        }
484    })
485}
486
487#[inline(never)]
488fn report_validation_error<'tcx>(
489    ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
490    cid: GlobalId<'tcx>,
491    error: InterpErrorInfo<'tcx>,
492    alloc_id: AllocId,
493) -> ErrorHandled {
494    if !#[allow(non_exhaustive_omitted_patterns)] match error.kind() {
    InterpErrorKind::UndefinedBehavior(_) => true,
    _ => false,
}matches!(error.kind(), InterpErrorKind::UndefinedBehavior(_)) {
495        // Some other error happened during validation, e.g. an unsupported operation.
496        return report_eval_error(ecx, cid, error);
497    }
498
499    let (error, backtrace) = error.into_parts();
500    backtrace.print_backtrace();
501
502    let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id);
503    let info = ecx.get_alloc_info(alloc_id);
504    let raw_bytes =
505        errors::RawBytesNote { size: info.size.bytes(), align: info.align.bytes(), bytes };
506
507    crate::const_eval::report(ecx, error, move |diag, span, frames| {
508        diag.span_label(span, "it is undefined behavior to use this value");
509        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.");
510        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
511        diag.subdiagnostic(raw_bytes);
512    })
513}