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