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::throw_inval;
10use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout};
11use rustc_middle::ty::print::with_no_trimmed_paths;
12use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
13use rustc_span::def_id::LocalDefId;
14use rustc_span::{Span, bug};
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    ensure_monomorphic_enough, intern_const_alloc_recursive, interp_ok, throw_exhaust,
23};
24use crate::{CTRL_C_RECEIVED, diagnostics};
25
26fn retry_codegen_mode_with_postanalysis<'tcx, K: TypeVisitable<TyCtxt<'tcx>>, V>(
27    key: ty::PseudoCanonicalInput<'tcx, K>,
28    f: impl FnOnce(ty::PseudoCanonicalInput<'tcx, K>) -> Result<V, ErrorHandled>,
29) -> Option<Result<V, ErrorHandled>> {
30    let ty::PseudoCanonicalInput { typing_env, value } = key;
31    match typing_env.typing_mode().assert_not_erased() {
32        // We are in codegen. It's very likely this constant has been evaluated in PostAnalysis
33        // before. Try to reuse this evaluation, and only re-run if we hit a `TooGeneric` error.
34        ty::TypingMode::Codegen => {
35            let with_postanalysis =
36                ty::TypingEnv::new(typing_env.param_env, ty::TypingMode::PostAnalysis);
37            let with_postanalysis = f(with_postanalysis.as_query_input(value));
38            match with_postanalysis {
39                Ok(_) | Err(ErrorHandled::Reported(..)) => return Some(with_postanalysis),
40                Err(ErrorHandled::TooGeneric(_)) => {}
41            }
42        }
43        ty::TypingMode::Coherence
44        | ty::TypingMode::Typeck { .. }
45        | ty::TypingMode::PostTypeckThroughBorrowck { .. }
46        | ty::TypingMode::PostBorrowck { .. }
47        | ty::TypingMode::Reflection
48        | ty::TypingMode::PostAnalysis => {}
49    }
50
51    None
52}
53
54fn setup_for_eval<'tcx>(
55    ecx: &mut CompileTimeInterpCx<'tcx>,
56    cid: GlobalId<'tcx>,
57    layout: TyAndLayout<'tcx>,
58) -> InterpResult<'tcx, (InternKind, MPlaceTy<'tcx>)> {
59    let tcx = *ecx.tcx;
60    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::AssocConst => true,
                _ => false,
            }) {
    {
        ::core::panicking::panic_fmt(format_args!("Unexpected DefKind: {0:?}",
                ecx.tcx.def_kind(cid.instance.def_id())));
    }
};assert!(
61        cid.promoted.is_some()
62            || matches!(
63                ecx.tcx.def_kind(cid.instance.def_id()),
64                DefKind::Const
65                    | DefKind::Static { .. }
66                    | DefKind::ConstParam
67                    | DefKind::AnonConst
68                    | DefKind::AssocConst
69            ),
70        "Unexpected DefKind: {:?}",
71        ecx.tcx.def_kind(cid.instance.def_id())
72    );
73    if !layout.is_sized() {
    ::core::panicking::panic("assertion failed: layout.is_sized()")
};assert!(layout.is_sized());
74
75    let intern_kind = if cid.promoted.is_some() {
76        InternKind::Promoted
77    } else {
78        match tcx.static_mutability(cid.instance.def_id()) {
79            Some(m) => InternKind::Static(m),
80            None => InternKind::Constant,
81        }
82    };
83
84    let return_place = if let InternKind::Static(_) = intern_kind {
85        create_static_alloc(ecx, cid.instance.def_id().expect_local(), layout)
86    } else {
87        ecx.allocate(layout, MemoryKind::Stack)
88    };
89
90    return_place.map(|ret| (intern_kind, ret))
91}
92
93{}
#[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("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(93u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("cid")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("cid");
                                                        NAME.as_str()
                                                    }], ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cid)
                                                            as &dyn ::tracing::field::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 ty =
                body.bound_return_ty(tcx).instantiate(tcx,
                        cid.instance.args).skip_norm_wip();
            ensure_monomorphic_enough(ty)?;
            let layout = ecx.layout_of(ty)?;
            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 /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs:106",
                                    "rustc_const_eval::const_eval::eval_queries",
                                    ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(106u32),
                                    ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::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 ::tracing::field::Value))])
                        });
                } else { ; }
            };
            {
                match (&body.arg_count, &0) {
                    (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 cid.promoted.is_none() &&
                    cid.instance.def.requires_caller_location(tcx) {
                do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(tcx.dcx().span_delayed_bug(body.span,
                                    "can't evaluate body with `#[track_caller]`"))));
            }
            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))]
94fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
95    ecx: &mut CompileTimeInterpCx<'tcx>,
96    cid: GlobalId<'tcx>,
97    body: &'tcx mir::Body<'tcx>,
98) -> InterpResult<'tcx, R> {
99    let tcx = *ecx.tcx;
100    let ty = body.bound_return_ty(tcx).instantiate(tcx, cid.instance.args).skip_norm_wip();
101    ensure_monomorphic_enough(ty)?;
102
103    let layout = ecx.layout_of(ty)?;
104    let (intern_kind, ret) = setup_for_eval(ecx, cid, layout)?;
105
106    trace!(
107        "eval_body_using_ecx: pushing stack frame for global: {}{}",
108        with_no_trimmed_paths!(ecx.tcx.def_path_str(cid.instance.def_id())),
109        cid.promoted.map_or_else(String::new, |p| format!("::{p:?}"))
110    );
111
112    // We are about to initialize a frame without any arguments,
113    // and without `#[track_caller]` support.
114    // Make sure that the body expects this.
115    // Note: Promoteds don't require a caller location,
116    // even when inside an `Instance` with `#[track_caller]`
117    assert_eq!(body.arg_count, 0);
118    if cid.promoted.is_none() && cid.instance.def.requires_caller_location(tcx) {
119        // FIXME: Once #131787 is fixed, turn this delayed bug into an assertion.
120        throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
121            tcx.dcx().span_delayed_bug(body.span, "can't evaluate body with `#[track_caller]`")
122        )));
123    }
124
125    // This can't use `init_stack_frame` since `body` is not a function,
126    // so computing its ABI would fail. It's also not worth it since there are no arguments to pass.
127    ecx.push_stack_frame_raw(
128        cid.instance,
129        body,
130        &ret.clone().into(),
131        ReturnContinuation::Stop { cleanup: false },
132    )?;
133    ecx.push_stack_frame_done()?;
134
135    // The main interpreter loop.
136    while ecx.step()? {
137        if CTRL_C_RECEIVED.load(Relaxed) {
138            throw_exhaust!(Interrupted);
139        }
140    }
141
142    intern_and_validate(ecx, cid, intern_kind, ret)
143}
144
145{}
#[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("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(145u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("cid")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("cid");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("val")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("val");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("ty")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("ty");
                                                        NAME.as_str()
                                                    }], ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cid)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&val)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
                                                            as &dyn ::tracing::field::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))]
146fn eval_trivial_const_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
147    ecx: &mut CompileTimeInterpCx<'tcx>,
148    cid: GlobalId<'tcx>,
149    val: ConstValue,
150    ty: Ty<'tcx>,
151) -> InterpResult<'tcx, R> {
152    let layout = ecx.layout_of(ty)?;
153    let (intern_kind, return_place) = setup_for_eval(ecx, cid, layout)?;
154
155    let opty = ecx.const_val_to_op(val, ty, Some(layout))?;
156    ecx.copy_op(&opty, &return_place)?;
157
158    intern_and_validate(ecx, cid, intern_kind, return_place)
159}
160
161fn intern_and_validate<'tcx, R: InterpretationResult<'tcx>>(
162    ecx: &mut CompileTimeInterpCx<'tcx>,
163    cid: GlobalId<'tcx>,
164    intern_kind: InternKind,
165    ret: MPlaceTy<'tcx>,
166) -> InterpResult<'tcx, R> {
167    // Intern the result
168    let intern_result = intern_const_alloc_recursive(ecx, intern_kind, &ret);
169
170    // Since evaluation had no errors, validate the resulting constant.
171    const_validate_mplace(ecx, &ret, cid)?;
172
173    // Only report this after validation, as validation produces much better diagnostics.
174    // FIXME: ensure validation always reports this and stop making interning care about it.
175
176    match intern_result {
177        Ok(()) => {}
178        Err(InternError::DanglingPointer) => {
179            do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(diagnostics::DanglingPtrInFinal {
                        span: ecx.tcx.span,
                        kind: intern_kind,
                    }))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
180                ecx.tcx.dcx().emit_err(diagnostics::DanglingPtrInFinal {
181                    span: ecx.tcx.span,
182                    kind: intern_kind
183                }),
184            )));
185        }
186        Err(InternError::BadMutablePointer) => {
187            do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(diagnostics::MutablePtrInFinal {
                        span: ecx.tcx.span,
                        kind: intern_kind,
                    }))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
188                ecx.tcx.dcx().emit_err(diagnostics::MutablePtrInFinal {
189                    span: ecx.tcx.span,
190                    kind: intern_kind
191                }),
192            )));
193        }
194        Err(InternError::ConstAllocNotGlobal) => {
195            do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(diagnostics::ConstHeapPtrInFinal {
                        span: ecx.tcx.span,
                    }))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
196                ecx.tcx.dcx().emit_err(diagnostics::ConstHeapPtrInFinal { span: ecx.tcx.span }),
197            )));
198        }
199        Err(InternError::PartialPointer) => {
200            do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(diagnostics::PartialPtrInFinal {
                        span: ecx.tcx.span,
                        kind: intern_kind,
                    }))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
201                ecx.tcx.dcx().emit_err(diagnostics::PartialPtrInFinal {
202                    span: ecx.tcx.span,
203                    kind: intern_kind
204                }),
205            )));
206        }
207    }
208
209    interp_ok(R::make_result(ret, ecx))
210}
211
212/// The `InterpCx` is only meant to be used to do field and index projections into constants for
213/// `simd_shuffle` and const patterns in match arms.
214///
215/// This should *not* be used to do any actual interpretation. In particular, alignment checks are
216/// turned off!
217///
218/// The function containing the `match` that is currently being analyzed may have generic bounds
219/// that inform us about the generic bounds of the constant. E.g., using an associated constant
220/// of a function's generic parameter will require knowledge about the bounds on the generic
221/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
222pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
223    tcx: TyCtxt<'tcx>,
224    root_span: Span,
225    typing_env: ty::TypingEnv<'tcx>,
226    can_access_mut_global: CanAccessMutGlobal,
227) -> CompileTimeInterpCx<'tcx> {
228    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs:228",
                        "rustc_const_eval::const_eval::eval_queries",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                        ::tracing_core::__macro_support::Option::Some(228u32),
                        ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("mk_eval_cx: {0:?}",
                                                    typing_env) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("mk_eval_cx: {:?}", typing_env);
229    InterpCx::new(
230        tcx,
231        root_span,
232        typing_env,
233        CompileTimeMachine::new(can_access_mut_global, CheckAlignment::No),
234    )
235}
236
237/// Create an interpreter context to inspect the given `ConstValue`.
238/// Returns both the context and an `OpTy` that represents the constant.
239pub fn mk_eval_cx_for_const_val<'tcx>(
240    tcx: TyCtxtAt<'tcx>,
241    typing_env: ty::TypingEnv<'tcx>,
242    val: mir::ConstValue,
243    ty: Ty<'tcx>,
244) -> Option<(CompileTimeInterpCx<'tcx>, OpTy<'tcx>)> {
245    let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, typing_env, CanAccessMutGlobal::No);
246    // FIXME: is it a problem to discard the error here?
247    let op = ecx.const_val_to_op(val, ty, None).discard_err()?;
248    Some((ecx, op))
249}
250
251/// This function converts an interpreter value into a MIR constant.
252///
253/// The `for_diagnostics` flag turns the usual rules for returning `ConstValue::Scalar` into a
254/// best-effort attempt. This is not okay for use in const-eval sine it breaks invariants rustc
255/// relies on, but it is okay for diagnostics which will just give up gracefully when they
256/// encounter an `Indirect` they cannot handle.
257{}
#[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("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(257u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("op")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("op");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("for_diagnostics")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("for_diagnostics");
                                                        NAME.as_str()
                                                    }], ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&op)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&for_diagnostics
                                                            as &dyn ::tracing::field::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 /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs:300",
                                    "rustc_const_eval::const_eval::eval_queries",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(300u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("immediate")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("immediate");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&immediate)
                                                        as &dyn ::tracing::field::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 /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs:313",
                                                    "rustc_const_eval::const_eval::eval_queries",
                                                    ::tracing::Level::DEBUG,
                                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                                    ::tracing_core::__macro_support::Option::Some(313u32),
                                                    ::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};
                                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("ScalarPair(a: {0:?}, b: {1:?})",
                                                                                a, b) as &dyn ::tracing::field::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);
                            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_span::macros::bug_impl(None,
                                format_args!("`Uninit` is not a valid value for {0}",
                                    op.layout.ty), Location::caller()),
                    },
            }
        }
    }
}#[instrument(skip(ecx), level = "debug")]
258pub(super) fn op_to_const<'tcx>(
259    ecx: &CompileTimeInterpCx<'tcx>,
260    op: &OpTy<'tcx>,
261    for_diagnostics: bool,
262) -> ConstValue {
263    // Handle ZST consistently and early.
264    if op.layout.is_zst() {
265        return ConstValue::ZeroSized;
266    }
267
268    // All scalar types should be stored as `ConstValue::Scalar`. This is needed to make
269    // `ConstValue::try_to_scalar` efficient; we want that to work for *all* constants of scalar
270    // type (it's used throughout the compiler and having it work just on literals is not enough)
271    // and we want it to be fast (i.e., don't go to an `Allocation` and reconstruct the `Scalar`
272    // from its byte-serialized form).
273    let force_as_immediate = match op.layout.backend_repr {
274        BackendRepr::Scalar(abi::Scalar::Initialized { .. }) => true,
275        // We don't *force* `ConstValue::Slice` for `ScalarPair`. This has the advantage that if the
276        // input `op` is a place, then turning it into a `ConstValue` and back into a `OpTy` will
277        // not have to generate any duplicate allocations (we preserve the original `AllocId` in
278        // `ConstValue::Indirect`). It means accessing the contents of a slice can be slow (since
279        // they can be stored as `ConstValue::Indirect`), but that's not relevant since we barely
280        // ever have to do this. (`try_get_slice_bytes_for_diagnostics` exists to provide this
281        // functionality.)
282        _ => false,
283    };
284    let immediate = if force_as_immediate {
285        match ecx.read_immediate(op).report_err() {
286            Ok(imm) => Right(imm),
287            Err(err) => {
288                if for_diagnostics {
289                    // This discard the error, but for diagnostics that's okay.
290                    op.as_mplace_or_imm()
291                } else {
292                    panic!("normalization works on validated constants: {err:?}")
293                }
294            }
295        }
296    } else {
297        op.as_mplace_or_imm()
298    };
299
300    debug!(?immediate);
301
302    match immediate {
303        Left(ref mplace) => {
304            let (prov, offset) =
305                mplace.ptr().into_pointer_or_addr().unwrap().prov_and_relative_offset();
306            let alloc_id = prov.alloc_id();
307            ConstValue::Indirect { alloc_id, offset }
308        }
309        // see comment on `let force_as_immediate` above
310        Right(imm) => match *imm {
311            Immediate::Scalar(x) => ConstValue::Scalar(x),
312            Immediate::ScalarPair(a, b) => {
313                debug!("ScalarPair(a: {:?}, b: {:?})", a, b);
314                // This codepath solely exists for `valtree_to_const_value` to not need to generate
315                // a `ConstValue::Indirect` for wide references, so it is tightly restricted to just
316                // that case.
317                let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs
318                debug_assert!(
319                    matches!(
320                        ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(),
321                        ty::Str | ty::Slice(..),
322                    ),
323                    "`ConstValue::Slice` is for slice-tailed types only, but got {}",
324                    imm.layout.ty,
325                );
326                let msg = "`op_to_const` on an immediate scalar pair must only be used on slice references to the beginning of an actual allocation";
327                let ptr = a.to_pointer(ecx);
328                let (prov, offset) =
329                    ptr.into_pointer_or_addr().expect(msg).prov_and_relative_offset();
330                let alloc_id = prov.alloc_id();
331                assert!(offset == abi::Size::ZERO, "{}", msg);
332                let meta = b.to_target_usize(ecx).expect(msg);
333                ConstValue::Slice { alloc_id, meta }
334            }
335            Immediate::Uninit => bug!("`Uninit` is not a valid value for {}", op.layout.ty),
336        },
337    }
338}
339
340{}
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("turn_into_const_value",
                                "rustc_const_eval::const_eval::eval_queries",
                                ::tracing::Level::DEBUG,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                ::tracing_core::__macro_support::Option::Some(340u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                ::tracing_core::field::FieldSet::new(&[{
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("constant")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("constant");
                                                    NAME.as_str()
                                                },
                                                {
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("key")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("key");
                                                    NAME.as_str()
                                                }], ::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};
                            meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&constant)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&key)
                                                        as &dyn ::tracing::field::Value))])
                        })
            } else {
                let span =
                    ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                {};
                span
            }
        };
    __tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
    (move ||
                {

                    #[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;
                    }
                    {
                        let cid = key.value;
                        let def_id = cid.instance.def.def_id();
                        let is_static = tcx.is_static(def_id);
                        let ecx =
                            mk_eval_cx_to_read_const_val(tcx,
                                tcx.def_span(key.value.instance.def_id()), key.typing_env,
                                CanAccessMutGlobal::from(is_static));
                        let mplace =
                            ecx.raw_const_to_mplace(constant).expect("can only fail if layout computation failed, \
        which should have given a good error before ever invoking this function");
                        if !(!is_static || cid.promoted.is_some()) {
                            {
                                ::core::panicking::panic_fmt(format_args!("the `eval_to_const_value_raw` query should not be used for statics, use `eval_to_allocation` instead"));
                            }
                        };
                        op_to_const(&ecx, &mplace.into(), false)
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs:340",
                        "rustc_const_eval::const_eval::eval_queries",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                        ::tracing_core::__macro_support::Option::Some(340u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("return")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("return");
                                            NAME.as_str()
                                        }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};
x;#[instrument(skip(tcx), level = "debug", ret)]
341pub(crate) fn turn_into_const_value<'tcx>(
342    tcx: TyCtxt<'tcx>,
343    constant: ConstAlloc<'tcx>,
344    key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
345) -> ConstValue {
346    let cid = key.value;
347    let def_id = cid.instance.def.def_id();
348    let is_static = tcx.is_static(def_id);
349    // This is just accessing an already computed constant, so no need to check alignment here.
350    let ecx = mk_eval_cx_to_read_const_val(
351        tcx,
352        tcx.def_span(key.value.instance.def_id()),
353        key.typing_env,
354        CanAccessMutGlobal::from(is_static),
355    );
356
357    let mplace = ecx.raw_const_to_mplace(constant).expect(
358        "can only fail if layout computation failed, \
359        which should have given a good error before ever invoking this function",
360    );
361    assert!(
362        !is_static || cid.promoted.is_some(),
363        "the `eval_to_const_value_raw` query should not be used for statics, use `eval_to_allocation` instead"
364    );
365
366    // Turn this into a proper constant.
367    op_to_const(&ecx, &mplace.into(), /* for diagnostics */ false)
368}
369
370{}
#[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("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(370u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("key")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("key");
                                                        NAME.as_str()
                                                    }], ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&key)
                                                            as &dyn ::tracing::field::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;
        }
        {
            crate::assert_typing_mode(key.typing_env.typing_mode());
            if let Some((value, _ty)) =
                    tcx.trivial_const(key.value.instance.def_id()) {
                return Ok(value);
            }
            if let Some(retry) =
                    retry_codegen_mode_with_postanalysis(key,
                        |key| tcx.eval_to_const_value_raw(key)) {
                return retry;
            }
            tcx.eval_to_allocation_raw(key).map(|val|
                    turn_into_const_value(tcx, val, key))
        }
    }
}#[instrument(skip(tcx), level = "debug")]
371pub fn eval_to_const_value_raw_provider<'tcx>(
372    tcx: TyCtxt<'tcx>,
373    key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
374) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
375    crate::assert_typing_mode(key.typing_env.typing_mode());
376
377    if let Some((value, _ty)) = tcx.trivial_const(key.value.instance.def_id()) {
378        return Ok(value);
379    }
380
381    if let Some(retry) =
382        retry_codegen_mode_with_postanalysis(key, |key| tcx.eval_to_const_value_raw(key))
383    {
384        return retry;
385    }
386
387    tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key))
388}
389
390{}
#[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("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(390u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("def_id")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("def_id");
                                                        NAME.as_str()
                                                    }], ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
                                                            as &dyn ::tracing::field::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")]
391pub fn eval_static_initializer_provider<'tcx>(
392    tcx: TyCtxt<'tcx>,
393    def_id: LocalDefId,
394) -> ::rustc_middle::mir::interpret::EvalStaticInitializerRawResult<'tcx> {
395    assert!(tcx.is_static(def_id.to_def_id()));
396
397    let instance = ty::Instance::mono(tcx, def_id.to_def_id());
398    let cid = rustc_middle::mir::interpret::GlobalId { instance, promoted: None };
399    eval_in_interpreter(tcx, cid, ty::TypingEnv::fully_monomorphized())
400}
401
402pub trait InterpretationResult<'tcx> {
403    /// This function takes the place where the result of the evaluation is stored
404    /// and prepares it for returning it in the appropriate format needed by the specific
405    /// evaluation query.
406    fn make_result(
407        mplace: MPlaceTy<'tcx>,
408        ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
409    ) -> Self;
410}
411
412impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> {
413    fn make_result(
414        mplace: MPlaceTy<'tcx>,
415        _ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
416    ) -> Self {
417        ConstAlloc { alloc_id: mplace.ptr().provenance.unwrap().alloc_id(), ty: mplace.layout.ty }
418    }
419}
420
421{}
#[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("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                    ::tracing_core::__macro_support::Option::Some(421u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("key")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("key");
                                                        NAME.as_str()
                                                    }], ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&key)
                                                            as &dyn ::tracing::field::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;
        }
        {
            crate::assert_typing_mode(key.typing_env.typing_mode());
            if let Some(retry) =
                    retry_codegen_mode_with_postanalysis(key,
                        |key| tcx.eval_to_allocation_raw(key)) {
                return retry;
            }
            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 {
                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 /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs:444",
                                        "rustc_const_eval::const_eval::eval_queries",
                                        ::tracing::Level::TRACE,
                                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
                                        ::tracing_core::__macro_support::Option::Some(444u32),
                                        ::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};
                                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("const eval: {0:?} ({1})",
                                                                    key, instance) as &dyn ::tracing::field::Value))])
                            });
                    } else { ; }
                };
            }
            eval_in_interpreter(tcx, key.value, key.typing_env)
        }
    }
}#[instrument(skip(tcx), level = "debug")]
422pub fn eval_to_allocation_raw_provider<'tcx>(
423    tcx: TyCtxt<'tcx>,
424    key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
425) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
426    crate::assert_typing_mode(key.typing_env.typing_mode());
427    if let Some(retry) =
428        retry_codegen_mode_with_postanalysis(key, |key| tcx.eval_to_allocation_raw(key))
429    {
430        return retry;
431    }
432
433    // This shouldn't be used for statics, since statics are conceptually places,
434    // not values -- so what we do here could break pointer identity.
435    assert!(key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id()));
436
437    if cfg!(debug_assertions) {
438        // Make sure we format the instance even if we do not print it.
439        // This serves as a regression test against an ICE on printing.
440        // The next two lines concatenated contain some discussion:
441        // https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/
442        // subject/anon_const_instance_printing/near/135980032
443        let instance = with_no_trimmed_paths!(key.value.instance.to_string());
444        trace!("const eval: {:?} ({})", key, instance);
445    }
446
447    eval_in_interpreter(tcx, key.value, key.typing_env)
448}
449
450fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
451    tcx: TyCtxt<'tcx>,
452    cid: GlobalId<'tcx>,
453    typing_env: ty::TypingEnv<'tcx>,
454) -> Result<R, ErrorHandled> {
455    let def = cid.instance.def.def_id();
456    let is_static = tcx.is_static(def);
457    let mut ecx = InterpCx::new(
458        tcx,
459        tcx.def_span(def),
460        typing_env,
461        // Statics (and promoteds inside statics) may access mutable global memory, because unlike consts
462        // they do not have to behave "as if" they were evaluated at runtime.
463        // For consts however we want to ensure they behave "as if" they were evaluated at runtime,
464        // so we have to reject reading mutable global memory.
465        CompileTimeMachine::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error),
466    );
467
468    let result = if let Some((value, ty)) = tcx.trivial_const(def) {
469        eval_trivial_const_using_ecx(&mut ecx, cid, value, ty)
470    } else {
471        ecx.load_mir(cid.instance.def, cid.promoted)
472            .and_then(|body| eval_body_using_ecx(&mut ecx, cid, body))
473    };
474    result.report_err().map_err(|error| report_eval_error(&ecx, cid, error))
475}
476
477#[inline(always)]
478fn const_validate_mplace<'tcx>(
479    ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
480    mplace: &MPlaceTy<'tcx>,
481    cid: GlobalId<'tcx>,
482) -> Result<(), ErrorHandled> {
483    let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
484    let mut ref_tracking = RefTracking::new(mplace.clone(), mplace.layout.ty);
485    let mut inner = false;
486    while let Some((mplace, path)) = ref_tracking.next() {
487        let mode = match ecx.tcx.static_mutability(cid.instance.def_id()) {
488            _ if cid.promoted.is_some() => CtfeValidationMode::Promoted,
489            Some(mutbl) => CtfeValidationMode::Static { mutbl }, // a `static`
490            None => {
491                // This is a normal `const` (not promoted).
492                // The outermost allocation is always only copied, so having `UnsafeCell` in there
493                // is okay despite them being in immutable memory.
494                CtfeValidationMode::Const { allow_immutable_unsafe_cell: !inner }
495            }
496        };
497        ecx.const_validate_place(&mplace.into(), path, &mut ref_tracking, mode)
498            .report_err()
499            // Instead of just reporting the `InterpError` via the usual machinery, we give a more targeted
500            // error about the validation failure.
501            .map_err(|error| report_validation_error(&ecx, cid, error, alloc_id))?;
502        inner = true;
503    }
504
505    Ok(())
506}
507
508#[inline(never)]
509fn report_eval_error<'tcx>(
510    ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
511    cid: GlobalId<'tcx>,
512    error: InterpErrorInfo<'tcx>,
513) -> ErrorHandled {
514    let (error, backtrace) = error.into_parts();
515    backtrace.print_backtrace();
516
517    super::report(ecx, error, |diag, span, frames| {
518        let num_frames = frames.len();
519        diag.span_label(
520            span,
521            ::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!(
522                "evaluation of `{instance}` failed {where_}",
523                instance = with_no_trimmed_paths!(cid.instance.to_string()),
524                where_ = if num_frames == 0 { "here" } else { "inside this call" },
525            ),
526        );
527        for span in crate::util::context_spans(*ecx.tcx, span, cid.instance.def_id()) {
528            diag.span_context(span);
529        }
530        for frame in frames {
531            diag.subdiagnostic(frame);
532        }
533    })
534}
535
536#[inline(never)]
537fn report_validation_error<'tcx>(
538    ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
539    cid: GlobalId<'tcx>,
540    error: InterpErrorInfo<'tcx>,
541    alloc_id: AllocId,
542) -> ErrorHandled {
543    if !#[allow(non_exhaustive_omitted_patterns)] match error.kind() {
    InterpErrorKind::UndefinedBehavior(_) => true,
    _ => false,
}matches!(error.kind(), InterpErrorKind::UndefinedBehavior(_)) {
544        // Some other error happened during validation, e.g. an unsupported operation.
545        return report_eval_error(ecx, cid, error);
546    }
547
548    let (error, backtrace) = error.into_parts();
549    backtrace.print_backtrace();
550
551    let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id);
552    let info = ecx.get_alloc_info(alloc_id);
553    let raw_bytes =
554        diagnostics::RawBytesNote { size: info.size.bytes(), align: info.align.bytes(), bytes };
555
556    crate::const_eval::report(ecx, error, move |diag, span, frames| {
557        diag.span_label(span, "it is undefined behavior to use this value");
558        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.");
559        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
560        diag.subdiagnostic(raw_bytes);
561    })
562}