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