1use std::sync::atomic::Ordering::Relaxed;
2
3use either::{Left, Right};
4use rustc_abi::{self as abi, BackendRepr};
5use rustc_errors::{E0080, msg};
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(
471 span,
472 rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("evaluation of `{$instance}` failed {$num_frames ->\n [0] here\n *[other] inside this call\n }"))msg!(
473 "evaluation of `{$instance}` failed {$num_frames ->
474 [0] here
475 *[other] inside this call
476 }"
477 ),
478 );
479 for frame in frames {
480 diag.subdiagnostic(frame);
481 }
482 diag.arg("instance", { let _guard = NoTrimmedGuard::new(); cid.instance.to_string() }with_no_trimmed_paths!(cid.instance.to_string()));
484 diag.arg("num_frames", num_frames);
485 },
486 )
487}
488
489#[inline(never)]
490fn report_validation_error<'tcx>(
491 ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
492 cid: GlobalId<'tcx>,
493 error: InterpErrorInfo<'tcx>,
494 alloc_id: AllocId,
495) -> ErrorHandled {
496 if !#[allow(non_exhaustive_omitted_patterns)] match error.kind() {
InterpErrorKind::UndefinedBehavior(_) => true,
_ => false,
}matches!(error.kind(), InterpErrorKind::UndefinedBehavior(_)) {
497 return report_eval_error(ecx, cid, error);
499 }
500
501 let (error, backtrace) = error.into_parts();
502 backtrace.print_backtrace();
503
504 let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id);
505 let info = ecx.get_alloc_info(alloc_id);
506 let raw_bytes =
507 errors::RawBytesNote { size: info.size.bytes(), align: info.align.bytes(), bytes };
508
509 crate::const_eval::report(
510 ecx,
511 error,
512 DUMMY_SP,
513 || crate::const_eval::get_span_and_frames(ecx.tcx, ecx.stack()),
514 move |diag, span, frames| {
515 diag.code(E0080);
517 diag.span_label(span, "it is undefined behavior to use this value");
518 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.");
519 for frame in frames {
520 diag.subdiagnostic(frame);
521 }
522 diag.subdiagnostic(raw_bytes);
523 },
524 )
525}