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).skip_norm_wip())?;
let (intern_kind, ret) = setup_for_eval(ecx, cid, layout)?;
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_const_eval/src/const_eval/eval_queries.rs: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.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 =
74 ecx.layout_of(body.bound_return_ty().instantiate(tcx, cid.instance.args).skip_norm_wip())?;
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.push_stack_frame_done()?;
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 => {}
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:395",
"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(395u32),
::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
376 if cfg!(debug_assertions) {
377 match key.typing_env.typing_mode() {
378 ty::TypingMode::PostAnalysis => {}
379 ty::TypingMode::Coherence
380 | ty::TypingMode::Analysis { .. }
381 | ty::TypingMode::Borrowck { .. }
382 | ty::TypingMode::PostBorrowckAnalysis { .. } => {
383 bug!(
384 "Const eval should always happens in PostAnalysis mode. See the comment in `InterpCx::new` for more details."
385 )
386 }
387 }
388
389 let instance = with_no_trimmed_paths!(key.value.instance.to_string());
395 trace!("const eval: {:?} ({})", key, instance);
396 }
397
398 eval_in_interpreter(tcx, key.value, key.typing_env)
399}
400
401fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
402 tcx: TyCtxt<'tcx>,
403 cid: GlobalId<'tcx>,
404 typing_env: ty::TypingEnv<'tcx>,
405) -> Result<R, ErrorHandled> {
406 let def = cid.instance.def.def_id();
407 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);
409
410 let is_static = tcx.is_static(def);
411 let mut ecx = InterpCx::new(
412 tcx,
413 tcx.def_span(def),
414 typing_env,
415 CompileTimeMachine::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error),
420 );
421
422 let result = if let Some((value, ty)) = tcx.trivial_const(def) {
423 eval_trivial_const_using_ecx(&mut ecx, cid, value, ty)
424 } else {
425 ecx.load_mir(cid.instance.def, cid.promoted)
426 .and_then(|body| eval_body_using_ecx(&mut ecx, cid, body))
427 };
428 result.report_err().map_err(|error| report_eval_error(&ecx, cid, error))
429}
430
431#[inline(always)]
432fn const_validate_mplace<'tcx>(
433 ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
434 mplace: &MPlaceTy<'tcx>,
435 cid: GlobalId<'tcx>,
436) -> Result<(), ErrorHandled> {
437 let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
438 let mut ref_tracking = RefTracking::new(mplace.clone(), mplace.layout.ty);
439 let mut inner = false;
440 while let Some((mplace, path)) = ref_tracking.next() {
441 let mode = match ecx.tcx.static_mutability(cid.instance.def_id()) {
442 _ if cid.promoted.is_some() => CtfeValidationMode::Promoted,
443 Some(mutbl) => CtfeValidationMode::Static { mutbl }, None => {
445 CtfeValidationMode::Const { allow_immutable_unsafe_cell: !inner }
449 }
450 };
451 ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)
452 .report_err()
453 .map_err(|error| report_validation_error(&ecx, cid, error, alloc_id))?;
456 inner = true;
457 }
458
459 Ok(())
460}
461
462#[inline(never)]
463fn report_eval_error<'tcx>(
464 ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
465 cid: GlobalId<'tcx>,
466 error: InterpErrorInfo<'tcx>,
467) -> ErrorHandled {
468 let (error, backtrace) = error.into_parts();
469 backtrace.print_backtrace();
470
471 super::report(ecx, error, |diag, span, frames| {
472 let num_frames = frames.len();
473 diag.span_label(
474 span,
475 ::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!(
476 "evaluation of `{instance}` failed {where_}",
477 instance = with_no_trimmed_paths!(cid.instance.to_string()),
478 where_ = if num_frames == 0 { "here" } else { "inside this call" },
479 ),
480 );
481 for frame in frames {
482 diag.subdiagnostic(frame);
483 }
484 })
485}
486
487#[inline(never)]
488fn report_validation_error<'tcx>(
489 ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
490 cid: GlobalId<'tcx>,
491 error: InterpErrorInfo<'tcx>,
492 alloc_id: AllocId,
493) -> ErrorHandled {
494 if !#[allow(non_exhaustive_omitted_patterns)] match error.kind() {
InterpErrorKind::UndefinedBehavior(_) => true,
_ => false,
}matches!(error.kind(), InterpErrorKind::UndefinedBehavior(_)) {
495 return report_eval_error(ecx, cid, error);
497 }
498
499 let (error, backtrace) = error.into_parts();
500 backtrace.print_backtrace();
501
502 let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id);
503 let info = ecx.get_alloc_info(alloc_id);
504 let raw_bytes =
505 errors::RawBytesNote { size: info.size.bytes(), align: info.align.bytes(), bytes };
506
507 crate::const_eval::report(ecx, error, move |diag, span, frames| {
508 diag.span_label(span, "it is undefined behavior to use this value");
509 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.");
510 if !frames.is_empty() {
::core::panicking::panic("assertion failed: frames.is_empty()")
};assert!(frames.is_empty()); diag.subdiagnostic(raw_bytes);
512 })
513}