1use std::sync::atomic::Ordering::Relaxed;
2
3use either::{Left, Right};
4use rustc_abi::{self as abi, BackendRepr};
5use rustc_errors::E0080;
6use rustc_hir::def::DefKind;
7use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo, ReportedErrorInfo};
8use rustc_middle::mir::{self, ConstAlloc, ConstValue};
9use rustc_middle::query::TyCtxtAt;
10use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout};
11use rustc_middle::ty::print::with_no_trimmed_paths;
12use rustc_middle::ty::{self, Ty, TyCtxt};
13use rustc_middle::{bug, throw_inval};
14use rustc_span::def_id::LocalDefId;
15use rustc_span::{DUMMY_SP, Span};
16use tracing::{debug, instrument, trace};
17
18use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine};
19use crate::const_eval::CheckAlignment;
20use crate::interpret::{
21 CtfeValidationMode, GlobalId, Immediate, InternError, InternKind, InterpCx, InterpErrorKind,
22 InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, ReturnContinuation, create_static_alloc,
23 intern_const_alloc_recursive, interp_ok, throw_exhaust,
24};
25use crate::{CTRL_C_RECEIVED, errors};
26
27fn setup_for_eval<'tcx>(
28 ecx: &mut CompileTimeInterpCx<'tcx>,
29 cid: GlobalId<'tcx>,
30 layout: TyAndLayout<'tcx>,
31) -> InterpResult<'tcx, (InternKind, MPlaceTy<'tcx>)> {
32 let tcx = *ecx.tcx;
33 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!(
34 cid.promoted.is_some()
35 || matches!(
36 ecx.tcx.def_kind(cid.instance.def_id()),
37 DefKind::Const
38 | DefKind::Static { .. }
39 | DefKind::ConstParam
40 | DefKind::AnonConst
41 | DefKind::InlineConst
42 | DefKind::AssocConst
43 ),
44 "Unexpected DefKind: {:?}",
45 ecx.tcx.def_kind(cid.instance.def_id())
46 );
47 if !layout.is_sized() {
::core::panicking::panic("assertion failed: layout.is_sized()")
};assert!(layout.is_sized());
48
49 let intern_kind = if cid.promoted.is_some() {
50 InternKind::Promoted
51 } else {
52 match tcx.static_mutability(cid.instance.def_id()) {
53 Some(m) => InternKind::Static(m),
54 None => InternKind::Constant,
55 }
56 };
57
58 let return_place = if let InternKind::Static(_) = intern_kind {
59 create_static_alloc(ecx, cid.instance.def_id().expect_local(), layout)
60 } else {
61 ecx.allocate(layout, MemoryKind::Stack)
62 };
63
64 return_place.map(|ret| (intern_kind, ret))
65}
66
67#[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(67u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&["cid"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cid)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: InterpResult<'tcx, R> = loop {};
return __tracing_attr_fake_return;
}
{
let tcx = *ecx.tcx;
let layout =
ecx.layout_of(body.bound_return_ty().instantiate(tcx,
cid.instance.args))?;
let (intern_kind, ret) = setup_for_eval(ecx, cid, layout)?;
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_const_eval/src/const_eval/eval_queries.rs:77",
"rustc_const_eval::const_eval::eval_queries",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
::tracing_core::__macro_support::Option::Some(77u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("eval_body_using_ecx: pushing stack frame for global: {0}{1}",
{
let _guard = NoTrimmedGuard::new();
ecx.tcx.def_path_str(cid.instance.def_id())
},
cid.promoted.map_or_else(String::new,
|p|
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("::{0:?}", p))
}))) as &dyn Value))])
});
} else { ; }
};
ecx.push_stack_frame_raw(cid.instance, body, &ret.clone().into(),
ReturnContinuation::Stop { cleanup: false })?;
ecx.storage_live_for_always_live_locals()?;
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))]
68fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
69 ecx: &mut CompileTimeInterpCx<'tcx>,
70 cid: GlobalId<'tcx>,
71 body: &'tcx mir::Body<'tcx>,
72) -> InterpResult<'tcx, R> {
73 let tcx = *ecx.tcx;
74 let layout = ecx.layout_of(body.bound_return_ty().instantiate(tcx, cid.instance.args))?;
75 let (intern_kind, ret) = setup_for_eval(ecx, cid, layout)?;
76
77 trace!(
78 "eval_body_using_ecx: pushing stack frame for global: {}{}",
79 with_no_trimmed_paths!(ecx.tcx.def_path_str(cid.instance.def_id())),
80 cid.promoted.map_or_else(String::new, |p| format!("::{p:?}"))
81 );
82
83 ecx.push_stack_frame_raw(
86 cid.instance,
87 body,
88 &ret.clone().into(),
89 ReturnContinuation::Stop { cleanup: false },
90 )?;
91 ecx.storage_live_for_always_live_locals()?;
92
93 while ecx.step()? {
95 if CTRL_C_RECEIVED.load(Relaxed) {
96 throw_exhaust!(Interrupted);
97 }
98 }
99
100 intern_and_validate(ecx, cid, intern_kind, ret)
101}
102
103#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("eval_trivial_const_using_ecx",
"rustc_const_eval::const_eval::eval_queries",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
::tracing_core::__macro_support::Option::Some(103u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&["cid", "val", "ty"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cid)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&val)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: InterpResult<'tcx, R> = loop {};
return __tracing_attr_fake_return;
}
{
let layout = ecx.layout_of(ty)?;
let (intern_kind, return_place) =
setup_for_eval(ecx, cid, layout)?;
let opty = ecx.const_val_to_op(val, ty, Some(layout))?;
ecx.copy_op(&opty, &return_place)?;
intern_and_validate(ecx, cid, intern_kind, return_place)
}
}
}#[instrument(level = "trace", skip(ecx))]
104fn eval_trivial_const_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
105 ecx: &mut CompileTimeInterpCx<'tcx>,
106 cid: GlobalId<'tcx>,
107 val: ConstValue,
108 ty: Ty<'tcx>,
109) -> InterpResult<'tcx, R> {
110 let layout = ecx.layout_of(ty)?;
111 let (intern_kind, return_place) = setup_for_eval(ecx, cid, layout)?;
112
113 let opty = ecx.const_val_to_op(val, ty, Some(layout))?;
114 ecx.copy_op(&opty, &return_place)?;
115
116 intern_and_validate(ecx, cid, intern_kind, return_place)
117}
118
119fn intern_and_validate<'tcx, R: InterpretationResult<'tcx>>(
120 ecx: &mut CompileTimeInterpCx<'tcx>,
121 cid: GlobalId<'tcx>,
122 intern_kind: InternKind,
123 ret: MPlaceTy<'tcx>,
124) -> InterpResult<'tcx, R> {
125 let intern_result = intern_const_alloc_recursive(ecx, intern_kind, &ret);
127
128 const_validate_mplace(ecx, &ret, cid)?;
130
131 match intern_result {
135 Ok(()) => {}
136 Err(InternError::DanglingPointer) => {
137 do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(errors::DanglingPtrInFinal {
span: ecx.tcx.span,
kind: intern_kind,
}))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
138 ecx.tcx
139 .dcx()
140 .emit_err(errors::DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind }),
141 )));
142 }
143 Err(InternError::BadMutablePointer) => {
144 do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(errors::MutablePtrInFinal {
span: ecx.tcx.span,
kind: intern_kind,
}))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
145 ecx.tcx
146 .dcx()
147 .emit_err(errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind }),
148 )));
149 }
150 Err(InternError::ConstAllocNotGlobal) => {
151 do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(errors::ConstHeapPtrInFinal {
span: ecx.tcx.span,
}))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
152 ecx.tcx.dcx().emit_err(errors::ConstHeapPtrInFinal { span: ecx.tcx.span }),
153 )));
154 }
155 Err(InternError::PartialPointer) => {
156 do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(errors::PartialPtrInFinal {
span: ecx.tcx.span,
kind: intern_kind,
}))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
157 ecx.tcx
158 .dcx()
159 .emit_err(errors::PartialPtrInFinal { span: ecx.tcx.span, kind: intern_kind }),
160 )));
161 }
162 }
163
164 interp_ok(R::make_result(ret, ecx))
165}
166
167pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
178 tcx: TyCtxt<'tcx>,
179 root_span: Span,
180 typing_env: ty::TypingEnv<'tcx>,
181 can_access_mut_global: CanAccessMutGlobal,
182) -> CompileTimeInterpCx<'tcx> {
183 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_const_eval/src/const_eval/eval_queries.rs:183",
"rustc_const_eval::const_eval::eval_queries",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
::tracing_core::__macro_support::Option::Some(183u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("mk_eval_cx: {0:?}",
typing_env) as &dyn Value))])
});
} else { ; }
};debug!("mk_eval_cx: {:?}", typing_env);
184 InterpCx::new(
185 tcx,
186 root_span,
187 typing_env,
188 CompileTimeMachine::new(can_access_mut_global, CheckAlignment::No),
189 )
190}
191
192pub fn mk_eval_cx_for_const_val<'tcx>(
195 tcx: TyCtxtAt<'tcx>,
196 typing_env: ty::TypingEnv<'tcx>,
197 val: mir::ConstValue,
198 ty: Ty<'tcx>,
199) -> Option<(CompileTimeInterpCx<'tcx>, OpTy<'tcx>)> {
200 let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, typing_env, CanAccessMutGlobal::No);
201 let op = ecx.const_val_to_op(val, ty, None).discard_err()?;
203 Some((ecx, op))
204}
205
206#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("op_to_const",
"rustc_const_eval::const_eval::eval_queries",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
::tracing_core::__macro_support::Option::Some(212u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&["op",
"for_diagnostics"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&op)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&for_diagnostics as
&dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: ConstValue = loop {};
return __tracing_attr_fake_return;
}
{
if op.layout.is_zst() { return ConstValue::ZeroSized; }
let force_as_immediate =
match op.layout.backend_repr {
BackendRepr::Scalar(abi::Scalar::Initialized { .. }) =>
true,
_ => false,
};
let immediate =
if force_as_immediate {
match ecx.read_immediate(op).report_err() {
Ok(imm) => Right(imm),
Err(err) => {
if for_diagnostics {
op.as_mplace_or_imm()
} else {
{
::core::panicking::panic_fmt(format_args!("normalization works on validated constants: {0:?}",
err));
}
}
}
}
} else { op.as_mplace_or_imm() };
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_const_eval/src/const_eval/eval_queries.rs:255",
"rustc_const_eval::const_eval::eval_queries",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
::tracing_core::__macro_support::Option::Some(255u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&["immediate"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&immediate)
as &dyn Value))])
});
} else { ; }
};
match immediate {
Left(ref mplace) => {
let (prov, offset) =
mplace.ptr().into_pointer_or_addr().unwrap().prov_and_relative_offset();
let alloc_id = prov.alloc_id();
ConstValue::Indirect { alloc_id, offset }
}
Right(imm) =>
match *imm {
Immediate::Scalar(x) => ConstValue::Scalar(x),
Immediate::ScalarPair(a, b) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_const_eval/src/const_eval/eval_queries.rs:268",
"rustc_const_eval::const_eval::eval_queries",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
::tracing_core::__macro_support::Option::Some(268u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("ScalarPair(a: {0:?}, b: {1:?})",
a, b) as &dyn Value))])
});
} else { ; }
};
let pointee_ty =
imm.layout.ty.builtin_deref(false).unwrap();
if true {
if !#[allow(non_exhaustive_omitted_patterns)] match ecx.tcx.struct_tail_for_codegen(pointee_ty,
ecx.typing_env()).kind() {
ty::Str | ty::Slice(..) => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("`ConstValue::Slice` is for slice-tailed types only, but got {0}",
imm.layout.ty));
}
};
};
let msg =
"`op_to_const` on an immediate scalar pair must only be used on slice references to the beginning of an actual allocation";
let ptr = a.to_pointer(ecx).expect(msg);
let (prov, offset) =
ptr.into_pointer_or_addr().expect(msg).prov_and_relative_offset();
let alloc_id = prov.alloc_id();
if !(offset == abi::Size::ZERO) {
{ ::core::panicking::panic_display(&msg); }
};
let meta = b.to_target_usize(ecx).expect(msg);
ConstValue::Slice { alloc_id, meta }
}
Immediate::Uninit =>
::rustc_middle::util::bug::bug_fmt(format_args!("`Uninit` is not a valid value for {0}",
op.layout.ty)),
},
}
}
}
}#[instrument(skip(ecx), level = "debug")]
213pub(super) fn op_to_const<'tcx>(
214 ecx: &CompileTimeInterpCx<'tcx>,
215 op: &OpTy<'tcx>,
216 for_diagnostics: bool,
217) -> ConstValue {
218 if op.layout.is_zst() {
220 return ConstValue::ZeroSized;
221 }
222
223 let force_as_immediate = match op.layout.backend_repr {
229 BackendRepr::Scalar(abi::Scalar::Initialized { .. }) => true,
230 _ => false,
238 };
239 let immediate = if force_as_immediate {
240 match ecx.read_immediate(op).report_err() {
241 Ok(imm) => Right(imm),
242 Err(err) => {
243 if for_diagnostics {
244 op.as_mplace_or_imm()
246 } else {
247 panic!("normalization works on validated constants: {err:?}")
248 }
249 }
250 }
251 } else {
252 op.as_mplace_or_imm()
253 };
254
255 debug!(?immediate);
256
257 match immediate {
258 Left(ref mplace) => {
259 let (prov, offset) =
260 mplace.ptr().into_pointer_or_addr().unwrap().prov_and_relative_offset();
261 let alloc_id = prov.alloc_id();
262 ConstValue::Indirect { alloc_id, offset }
263 }
264 Right(imm) => match *imm {
266 Immediate::Scalar(x) => ConstValue::Scalar(x),
267 Immediate::ScalarPair(a, b) => {
268 debug!("ScalarPair(a: {:?}, b: {:?})", a, b);
269 let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); debug_assert!(
274 matches!(
275 ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(),
276 ty::Str | ty::Slice(..),
277 ),
278 "`ConstValue::Slice` is for slice-tailed types only, but got {}",
279 imm.layout.ty,
280 );
281 let msg = "`op_to_const` on an immediate scalar pair must only be used on slice references to the beginning of an actual allocation";
282 let ptr = a.to_pointer(ecx).expect(msg);
283 let (prov, offset) =
284 ptr.into_pointer_or_addr().expect(msg).prov_and_relative_offset();
285 let alloc_id = prov.alloc_id();
286 assert!(offset == abi::Size::ZERO, "{}", msg);
287 let meta = b.to_target_usize(ecx).expect(msg);
288 ConstValue::Slice { alloc_id, meta }
289 }
290 Immediate::Uninit => bug!("`Uninit` is not a valid value for {}", op.layout.ty),
291 },
292 }
293}
294
295x;#[instrument(skip(tcx), level = "debug", ret)]
296pub(crate) fn turn_into_const_value<'tcx>(
297 tcx: TyCtxt<'tcx>,
298 constant: ConstAlloc<'tcx>,
299 key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
300) -> ConstValue {
301 let cid = key.value;
302 let def_id = cid.instance.def.def_id();
303 let is_static = tcx.is_static(def_id);
304 let ecx = mk_eval_cx_to_read_const_val(
306 tcx,
307 tcx.def_span(key.value.instance.def_id()),
308 key.typing_env,
309 CanAccessMutGlobal::from(is_static),
310 );
311
312 let mplace = ecx.raw_const_to_mplace(constant).expect(
313 "can only fail if layout computation failed, \
314 which should have given a good error before ever invoking this function",
315 );
316 assert!(
317 !is_static || cid.promoted.is_some(),
318 "the `eval_to_const_value_raw` query should not be used for statics, use `eval_to_allocation` instead"
319 );
320
321 op_to_const(&ecx, &mplace.into(), false)
323}
324
325#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("eval_to_const_value_raw_provider",
"rustc_const_eval::const_eval::eval_queries",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
::tracing_core::__macro_support::Option::Some(325u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&["key"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&key)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> =
loop {};
return __tracing_attr_fake_return;
}
{
if let Some((value, _ty)) =
tcx.trivial_const(key.value.instance.def_id()) {
return Ok(value);
}
tcx.eval_to_allocation_raw(key).map(|val|
turn_into_const_value(tcx, val, key))
}
}
}#[instrument(skip(tcx), level = "debug")]
326pub fn eval_to_const_value_raw_provider<'tcx>(
327 tcx: TyCtxt<'tcx>,
328 key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
329) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
330 if let Some((value, _ty)) = tcx.trivial_const(key.value.instance.def_id()) {
331 return Ok(value);
332 }
333 tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key))
334}
335
336#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("eval_static_initializer_provider",
"rustc_const_eval::const_eval::eval_queries",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
::tracing_core::__macro_support::Option::Some(336u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&["def_id"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
::rustc_middle::mir::interpret::EvalStaticInitializerRawResult<'tcx> =
loop {};
return __tracing_attr_fake_return;
}
{
if !tcx.is_static(def_id.to_def_id()) {
::core::panicking::panic("assertion failed: tcx.is_static(def_id.to_def_id())")
};
let instance = ty::Instance::mono(tcx, def_id.to_def_id());
let cid =
rustc_middle::mir::interpret::GlobalId {
instance,
promoted: None,
};
eval_in_interpreter(tcx, cid,
ty::TypingEnv::fully_monomorphized())
}
}
}#[instrument(skip(tcx), level = "debug")]
337pub fn eval_static_initializer_provider<'tcx>(
338 tcx: TyCtxt<'tcx>,
339 def_id: LocalDefId,
340) -> ::rustc_middle::mir::interpret::EvalStaticInitializerRawResult<'tcx> {
341 assert!(tcx.is_static(def_id.to_def_id()));
342
343 let instance = ty::Instance::mono(tcx, def_id.to_def_id());
344 let cid = rustc_middle::mir::interpret::GlobalId { instance, promoted: None };
345 eval_in_interpreter(tcx, cid, ty::TypingEnv::fully_monomorphized())
346}
347
348pub trait InterpretationResult<'tcx> {
349 fn make_result(
353 mplace: MPlaceTy<'tcx>,
354 ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
355 ) -> Self;
356}
357
358impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> {
359 fn make_result(
360 mplace: MPlaceTy<'tcx>,
361 _ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
362 ) -> Self {
363 ConstAlloc { alloc_id: mplace.ptr().provenance.unwrap().alloc_id(), ty: mplace.layout.ty }
364 }
365}
366
367#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("eval_to_allocation_raw_provider",
"rustc_const_eval::const_eval::eval_queries",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/const_eval/eval_queries.rs"),
::tracing_core::__macro_support::Option::Some(367u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&["key"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&key)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> =
loop {};
return __tracing_attr_fake_return;
}
{
if !(key.value.promoted.is_some() ||
!tcx.is_static(key.value.instance.def_id())) {
::core::panicking::panic("assertion failed: key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id())")
};
if true {
match (&key.typing_env.typing_mode,
&ty::TypingMode::PostAnalysis) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
};
};
if true {
let instance =
{
let _guard = NoTrimmedGuard::new();
key.value.instance.to_string()
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_const_eval/src/const_eval/eval_queries.rs:385",
"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(385u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("const eval: {0:?} ({1})",
key, instance) as &dyn Value))])
});
} else { ; }
};
}
eval_in_interpreter(tcx, key.value, key.typing_env)
}
}
}#[instrument(skip(tcx), level = "debug")]
368pub fn eval_to_allocation_raw_provider<'tcx>(
369 tcx: TyCtxt<'tcx>,
370 key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
371) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
372 assert!(key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id()));
375 debug_assert_eq!(key.typing_env.typing_mode, ty::TypingMode::PostAnalysis);
378 if cfg!(debug_assertions) {
379 let instance = with_no_trimmed_paths!(key.value.instance.to_string());
385 trace!("const eval: {:?} ({})", key, instance);
386 }
387
388 eval_in_interpreter(tcx, key.value, key.typing_env)
389}
390
391fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
392 tcx: TyCtxt<'tcx>,
393 cid: GlobalId<'tcx>,
394 typing_env: ty::TypingEnv<'tcx>,
395) -> Result<R, ErrorHandled> {
396 let def = cid.instance.def.def_id();
397 if true {
if !!tcx.is_type_const(def) {
{
::core::panicking::panic_fmt(format_args!("CTFE tried to evaluate type-const: {0:?}",
def));
}
};
};debug_assert!(!tcx.is_type_const(def), "CTFE tried to evaluate type-const: {:?}", def);
399
400 let is_static = tcx.is_static(def);
401 let mut ecx = InterpCx::new(
402 tcx,
403 tcx.def_span(def),
404 typing_env,
405 CompileTimeMachine::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error),
410 );
411
412 let result = if let Some((value, ty)) = tcx.trivial_const(def) {
413 eval_trivial_const_using_ecx(&mut ecx, cid, value, ty)
414 } else {
415 ecx.load_mir(cid.instance.def, cid.promoted)
416 .and_then(|body| eval_body_using_ecx(&mut ecx, cid, body))
417 };
418 result.report_err().map_err(|error| report_eval_error(&ecx, cid, error))
419}
420
421#[inline(always)]
422fn const_validate_mplace<'tcx>(
423 ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
424 mplace: &MPlaceTy<'tcx>,
425 cid: GlobalId<'tcx>,
426) -> Result<(), ErrorHandled> {
427 let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
428 let mut ref_tracking = RefTracking::new(mplace.clone());
429 let mut inner = false;
430 while let Some((mplace, path)) = ref_tracking.next() {
431 let mode = match ecx.tcx.static_mutability(cid.instance.def_id()) {
432 _ if cid.promoted.is_some() => CtfeValidationMode::Promoted,
433 Some(mutbl) => CtfeValidationMode::Static { mutbl }, None => {
435 CtfeValidationMode::Const { allow_immutable_unsafe_cell: !inner }
439 }
440 };
441 ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)
442 .report_err()
443 .map_err(|error| report_validation_error(&ecx, cid, error, alloc_id))?;
446 inner = true;
447 }
448
449 Ok(())
450}
451
452#[inline(never)]
453fn report_eval_error<'tcx>(
454 ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
455 cid: GlobalId<'tcx>,
456 error: InterpErrorInfo<'tcx>,
457) -> ErrorHandled {
458 let (error, backtrace) = error.into_parts();
459 backtrace.print_backtrace();
460
461 super::report(
462 ecx,
463 error,
464 DUMMY_SP,
465 || super::get_span_and_frames(ecx.tcx, ecx.stack()),
466 |diag, span, frames| {
467 let num_frames = frames.len();
468 diag.code(E0080);
470 diag.span_label(span, crate::fluent_generated::const_eval_error);
471 for frame in frames {
472 diag.subdiagnostic(frame);
473 }
474 diag.arg("instance", { let _guard = NoTrimmedGuard::new(); cid.instance.to_string() }with_no_trimmed_paths!(cid.instance.to_string()));
476 diag.arg("num_frames", num_frames);
477 },
478 )
479}
480
481#[inline(never)]
482fn report_validation_error<'tcx>(
483 ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
484 cid: GlobalId<'tcx>,
485 error: InterpErrorInfo<'tcx>,
486 alloc_id: AllocId,
487) -> ErrorHandled {
488 if !#[allow(non_exhaustive_omitted_patterns)] match error.kind() {
InterpErrorKind::UndefinedBehavior(_) => true,
_ => false,
}matches!(error.kind(), InterpErrorKind::UndefinedBehavior(_)) {
489 return report_eval_error(ecx, cid, error);
491 }
492
493 let (error, backtrace) = error.into_parts();
494 backtrace.print_backtrace();
495
496 let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id);
497 let info = ecx.get_alloc_info(alloc_id);
498 let raw_bytes =
499 errors::RawBytesNote { size: info.size.bytes(), align: info.align.bytes(), bytes };
500
501 crate::const_eval::report(
502 ecx,
503 error,
504 DUMMY_SP,
505 || crate::const_eval::get_span_and_frames(ecx.tcx, ecx.stack()),
506 move |diag, span, frames| {
507 diag.code(E0080);
509 diag.span_label(span, crate::fluent_generated::const_eval_validation_failure);
510 diag.note(crate::fluent_generated::const_eval_validation_failure_note);
511 for frame in frames {
512 diag.subdiagnostic(frame);
513 }
514 diag.subdiagnostic(raw_bytes);
515 },
516 )
517}