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