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 ensure_monomorphic_enough, intern_const_alloc_recursive, interp_ok, throw_exhaust,
23};
24use crate::{CTRL_C_RECEIVED, diagnostics};
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::Reflection
48 | ty::TypingMode::PostAnalysis => {}
49 }
50
51 None
52}
53
54fn setup_for_eval<'tcx>(
55 ecx: &mut CompileTimeInterpCx<'tcx>,
56 cid: GlobalId<'tcx>,
57 layout: TyAndLayout<'tcx>,
58) -> InterpResult<'tcx, (InternKind, MPlaceTy<'tcx>)> {
59 let tcx = *ecx.tcx;
60 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::AssocConst { .. } => true,
_ => false,
}) {
{
::core::panicking::panic_fmt(format_args!("Unexpected DefKind: {0:?}",
ecx.tcx.def_kind(cid.instance.def_id())));
}
};assert!(
61 cid.promoted.is_some()
62 || matches!(
63 ecx.tcx.def_kind(cid.instance.def_id()),
64 DefKind::Const { .. }
65 | DefKind::Static { .. }
66 | DefKind::ConstParam
67 | DefKind::AnonConst
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(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("cid")
}> =
::tracing::__macro_support::FieldName::new("cid");
NAME.as_str()
}], ::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cid)
as &dyn ::tracing::field::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 ty =
body.bound_return_ty(tcx).instantiate(tcx,
cid.instance.args).skip_norm_wip();
ensure_monomorphic_enough(ty)?;
let layout = ecx.layout_of(ty)?;
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:106",
"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(106u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::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 ::tracing::field::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 ty = body.bound_return_ty(tcx).instantiate(tcx, cid.instance.args).skip_norm_wip();
101 ensure_monomorphic_enough(ty)?;
102
103 let layout = ecx.layout_of(ty)?;
104 let (intern_kind, ret) = setup_for_eval(ecx, cid, layout)?;
105
106 trace!(
107 "eval_body_using_ecx: pushing stack frame for global: {}{}",
108 with_no_trimmed_paths!(ecx.tcx.def_path_str(cid.instance.def_id())),
109 cid.promoted.map_or_else(String::new, |p| format!("::{p:?}"))
110 );
111
112 ecx.push_stack_frame_raw(
115 cid.instance,
116 body,
117 &ret.clone().into(),
118 ReturnContinuation::Stop { cleanup: false },
119 )?;
120 ecx.push_stack_frame_done()?;
121
122 while ecx.step()? {
124 if CTRL_C_RECEIVED.load(Relaxed) {
125 throw_exhaust!(Interrupted);
126 }
127 }
128
129 intern_and_validate(ecx, cid, intern_kind, ret)
130}
131
132#[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(132u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("cid")
}> =
::tracing::__macro_support::FieldName::new("cid");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("val")
}> =
::tracing::__macro_support::FieldName::new("val");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("ty")
}> =
::tracing::__macro_support::FieldName::new("ty");
NAME.as_str()
}], ::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cid)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&val)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
as &dyn ::tracing::field::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))]
133fn eval_trivial_const_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
134 ecx: &mut CompileTimeInterpCx<'tcx>,
135 cid: GlobalId<'tcx>,
136 val: ConstValue,
137 ty: Ty<'tcx>,
138) -> InterpResult<'tcx, R> {
139 let layout = ecx.layout_of(ty)?;
140 let (intern_kind, return_place) = setup_for_eval(ecx, cid, layout)?;
141
142 let opty = ecx.const_val_to_op(val, ty, Some(layout))?;
143 ecx.copy_op(&opty, &return_place)?;
144
145 intern_and_validate(ecx, cid, intern_kind, return_place)
146}
147
148fn intern_and_validate<'tcx, R: InterpretationResult<'tcx>>(
149 ecx: &mut CompileTimeInterpCx<'tcx>,
150 cid: GlobalId<'tcx>,
151 intern_kind: InternKind,
152 ret: MPlaceTy<'tcx>,
153) -> InterpResult<'tcx, R> {
154 let intern_result = intern_const_alloc_recursive(ecx, intern_kind, &ret);
156
157 const_validate_mplace(ecx, &ret, cid)?;
159
160 match intern_result {
164 Ok(()) => {}
165 Err(InternError::DanglingPointer) => {
166 do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(diagnostics::DanglingPtrInFinal {
span: ecx.tcx.span,
kind: intern_kind,
}))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
167 ecx.tcx.dcx().emit_err(diagnostics::DanglingPtrInFinal {
168 span: ecx.tcx.span,
169 kind: intern_kind
170 }),
171 )));
172 }
173 Err(InternError::BadMutablePointer) => {
174 do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(diagnostics::MutablePtrInFinal {
span: ecx.tcx.span,
kind: intern_kind,
}))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
175 ecx.tcx.dcx().emit_err(diagnostics::MutablePtrInFinal {
176 span: ecx.tcx.span,
177 kind: intern_kind
178 }),
179 )));
180 }
181 Err(InternError::ConstAllocNotGlobal) => {
182 do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(diagnostics::ConstHeapPtrInFinal {
span: ecx.tcx.span,
}))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
183 ecx.tcx.dcx().emit_err(diagnostics::ConstHeapPtrInFinal { span: ecx.tcx.span }),
184 )));
185 }
186 Err(InternError::PartialPointer) => {
187 do yeet ::rustc_middle::mir::interpret::InterpErrorKind::InvalidProgram(::rustc_middle::mir::interpret::InvalidProgramInfo::AlreadyReported(ReportedErrorInfo::non_const_eval_error(ecx.tcx.dcx().emit_err(diagnostics::PartialPtrInFinal {
span: ecx.tcx.span,
kind: intern_kind,
}))));throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
188 ecx.tcx.dcx().emit_err(diagnostics::PartialPtrInFinal {
189 span: ecx.tcx.span,
190 kind: intern_kind
191 }),
192 )));
193 }
194 }
195
196 interp_ok(R::make_result(ret, ecx))
197}
198
199pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
210 tcx: TyCtxt<'tcx>,
211 root_span: Span,
212 typing_env: ty::TypingEnv<'tcx>,
213 can_access_mut_global: CanAccessMutGlobal,
214) -> CompileTimeInterpCx<'tcx> {
215 {
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:215",
"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(215u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("mk_eval_cx: {0:?}",
typing_env) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("mk_eval_cx: {:?}", typing_env);
216 InterpCx::new(
217 tcx,
218 root_span,
219 typing_env,
220 CompileTimeMachine::new(can_access_mut_global, CheckAlignment::No),
221 )
222}
223
224pub fn mk_eval_cx_for_const_val<'tcx>(
227 tcx: TyCtxtAt<'tcx>,
228 typing_env: ty::TypingEnv<'tcx>,
229 val: mir::ConstValue,
230 ty: Ty<'tcx>,
231) -> Option<(CompileTimeInterpCx<'tcx>, OpTy<'tcx>)> {
232 let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, typing_env, CanAccessMutGlobal::No);
233 let op = ecx.const_val_to_op(val, ty, None).discard_err()?;
235 Some((ecx, op))
236}
237
238#[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(244u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("op")
}> =
::tracing::__macro_support::FieldName::new("op");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("for_diagnostics")
}> =
::tracing::__macro_support::FieldName::new("for_diagnostics");
NAME.as_str()
}], ::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&op)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&for_diagnostics
as &dyn ::tracing::field::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:287",
"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(287u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("immediate")
}> =
::tracing::__macro_support::FieldName::new("immediate");
NAME.as_str()
}], ::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&immediate)
as &dyn ::tracing::field::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:300",
"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(300u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("ScalarPair(a: {0:?}, b: {1:?})",
a, b) as &dyn ::tracing::field::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")]
245pub(super) fn op_to_const<'tcx>(
246 ecx: &CompileTimeInterpCx<'tcx>,
247 op: &OpTy<'tcx>,
248 for_diagnostics: bool,
249) -> ConstValue {
250 if op.layout.is_zst() {
252 return ConstValue::ZeroSized;
253 }
254
255 let force_as_immediate = match op.layout.backend_repr {
261 BackendRepr::Scalar(abi::Scalar::Initialized { .. }) => true,
262 _ => false,
270 };
271 let immediate = if force_as_immediate {
272 match ecx.read_immediate(op).report_err() {
273 Ok(imm) => Right(imm),
274 Err(err) => {
275 if for_diagnostics {
276 op.as_mplace_or_imm()
278 } else {
279 panic!("normalization works on validated constants: {err:?}")
280 }
281 }
282 }
283 } else {
284 op.as_mplace_or_imm()
285 };
286
287 debug!(?immediate);
288
289 match immediate {
290 Left(ref mplace) => {
291 let (prov, offset) =
292 mplace.ptr().into_pointer_or_addr().unwrap().prov_and_relative_offset();
293 let alloc_id = prov.alloc_id();
294 ConstValue::Indirect { alloc_id, offset }
295 }
296 Right(imm) => match *imm {
298 Immediate::Scalar(x) => ConstValue::Scalar(x),
299 Immediate::ScalarPair(a, b) => {
300 debug!("ScalarPair(a: {:?}, b: {:?})", a, b);
301 let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); debug_assert!(
306 matches!(
307 ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(),
308 ty::Str | ty::Slice(..),
309 ),
310 "`ConstValue::Slice` is for slice-tailed types only, but got {}",
311 imm.layout.ty,
312 );
313 let msg = "`op_to_const` on an immediate scalar pair must only be used on slice references to the beginning of an actual allocation";
314 let ptr = a.to_pointer(ecx).expect(msg);
315 let (prov, offset) =
316 ptr.into_pointer_or_addr().expect(msg).prov_and_relative_offset();
317 let alloc_id = prov.alloc_id();
318 assert!(offset == abi::Size::ZERO, "{}", msg);
319 let meta = b.to_target_usize(ecx).expect(msg);
320 ConstValue::Slice { alloc_id, meta }
321 }
322 Immediate::Uninit => bug!("`Uninit` is not a valid value for {}", op.layout.ty),
323 },
324 }
325}
326
327x;#[instrument(skip(tcx), level = "debug", ret)]
328pub(crate) fn turn_into_const_value<'tcx>(
329 tcx: TyCtxt<'tcx>,
330 constant: ConstAlloc<'tcx>,
331 key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
332) -> ConstValue {
333 let cid = key.value;
334 let def_id = cid.instance.def.def_id();
335 let is_static = tcx.is_static(def_id);
336 let ecx = mk_eval_cx_to_read_const_val(
338 tcx,
339 tcx.def_span(key.value.instance.def_id()),
340 key.typing_env,
341 CanAccessMutGlobal::from(is_static),
342 );
343
344 let mplace = ecx.raw_const_to_mplace(constant).expect(
345 "can only fail if layout computation failed, \
346 which should have given a good error before ever invoking this function",
347 );
348 assert!(
349 !is_static || cid.promoted.is_some(),
350 "the `eval_to_const_value_raw` query should not be used for statics, use `eval_to_allocation` instead"
351 );
352
353 op_to_const(&ecx, &mplace.into(), false)
355}
356
357#[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(357u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("key")
}> =
::tracing::__macro_support::FieldName::new("key");
NAME.as_str()
}], ::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&key)
as &dyn ::tracing::field::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")]
358pub fn eval_to_const_value_raw_provider<'tcx>(
359 tcx: TyCtxt<'tcx>,
360 key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
361) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
362 crate::assert_typing_mode(key.typing_env.typing_mode());
363
364 if let Some((value, _ty)) = tcx.trivial_const(key.value.instance.def_id()) {
365 return Ok(value);
366 }
367
368 if let Some(retry) =
369 retry_codegen_mode_with_postanalysis(key, |key| tcx.eval_to_const_value_raw(key))
370 {
371 return retry;
372 }
373
374 tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key))
375}
376
377#[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(377u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
as &dyn ::tracing::field::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")]
378pub fn eval_static_initializer_provider<'tcx>(
379 tcx: TyCtxt<'tcx>,
380 def_id: LocalDefId,
381) -> ::rustc_middle::mir::interpret::EvalStaticInitializerRawResult<'tcx> {
382 assert!(tcx.is_static(def_id.to_def_id()));
383
384 let instance = ty::Instance::mono(tcx, def_id.to_def_id());
385 let cid = rustc_middle::mir::interpret::GlobalId { instance, promoted: None };
386 eval_in_interpreter(tcx, cid, ty::TypingEnv::fully_monomorphized())
387}
388
389pub trait InterpretationResult<'tcx> {
390 fn make_result(
394 mplace: MPlaceTy<'tcx>,
395 ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
396 ) -> Self;
397}
398
399impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> {
400 fn make_result(
401 mplace: MPlaceTy<'tcx>,
402 _ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
403 ) -> Self {
404 ConstAlloc { alloc_id: mplace.ptr().provenance.unwrap().alloc_id(), ty: mplace.layout.ty }
405 }
406}
407
408#[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(408u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::const_eval::eval_queries"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("key")
}> =
::tracing::__macro_support::FieldName::new("key");
NAME.as_str()
}], ::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&key)
as &dyn ::tracing::field::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:431",
"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(431u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("const eval: {0:?} ({1})",
key, instance) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
}
eval_in_interpreter(tcx, key.value, key.typing_env)
}
}
}#[instrument(skip(tcx), level = "debug")]
409pub fn eval_to_allocation_raw_provider<'tcx>(
410 tcx: TyCtxt<'tcx>,
411 key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
412) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
413 crate::assert_typing_mode(key.typing_env.typing_mode());
414 if let Some(retry) =
415 retry_codegen_mode_with_postanalysis(key, |key| tcx.eval_to_allocation_raw(key))
416 {
417 return retry;
418 }
419
420 assert!(key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id()));
423
424 if cfg!(debug_assertions) {
425 let instance = with_no_trimmed_paths!(key.value.instance.to_string());
431 trace!("const eval: {:?} ({})", key, instance);
432 }
433
434 eval_in_interpreter(tcx, key.value, key.typing_env)
435}
436
437fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
438 tcx: TyCtxt<'tcx>,
439 cid: GlobalId<'tcx>,
440 typing_env: ty::TypingEnv<'tcx>,
441) -> Result<R, ErrorHandled> {
442 let def = cid.instance.def.def_id();
443 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);
445
446 let is_static = tcx.is_static(def);
447 let mut ecx = InterpCx::new(
448 tcx,
449 tcx.def_span(def),
450 typing_env,
451 CompileTimeMachine::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error),
456 );
457
458 let result = if let Some((value, ty)) = tcx.trivial_const(def) {
459 eval_trivial_const_using_ecx(&mut ecx, cid, value, ty)
460 } else {
461 ecx.load_mir(cid.instance.def, cid.promoted)
462 .and_then(|body| eval_body_using_ecx(&mut ecx, cid, body))
463 };
464 result.report_err().map_err(|error| report_eval_error(&ecx, cid, error))
465}
466
467#[inline(always)]
468fn const_validate_mplace<'tcx>(
469 ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
470 mplace: &MPlaceTy<'tcx>,
471 cid: GlobalId<'tcx>,
472) -> Result<(), ErrorHandled> {
473 let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
474 let mut ref_tracking = RefTracking::new(mplace.clone(), mplace.layout.ty);
475 let mut inner = false;
476 while let Some((mplace, path)) = ref_tracking.next() {
477 let mode = match ecx.tcx.static_mutability(cid.instance.def_id()) {
478 _ if cid.promoted.is_some() => CtfeValidationMode::Promoted,
479 Some(mutbl) => CtfeValidationMode::Static { mutbl }, None => {
481 CtfeValidationMode::Const { allow_immutable_unsafe_cell: !inner }
485 }
486 };
487 ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)
488 .report_err()
489 .map_err(|error| report_validation_error(&ecx, cid, error, alloc_id))?;
492 inner = true;
493 }
494
495 Ok(())
496}
497
498#[inline(never)]
499fn report_eval_error<'tcx>(
500 ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
501 cid: GlobalId<'tcx>,
502 error: InterpErrorInfo<'tcx>,
503) -> ErrorHandled {
504 let (error, backtrace) = error.into_parts();
505 backtrace.print_backtrace();
506
507 super::report(ecx, error, |diag, span, frames| {
508 let num_frames = frames.len();
509 diag.span_label(
510 span,
511 ::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!(
512 "evaluation of `{instance}` failed {where_}",
513 instance = with_no_trimmed_paths!(cid.instance.to_string()),
514 where_ = if num_frames == 0 { "here" } else { "inside this call" },
515 ),
516 );
517 for frame in frames {
518 diag.subdiagnostic(frame);
519 }
520 })
521}
522
523#[inline(never)]
524fn report_validation_error<'tcx>(
525 ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
526 cid: GlobalId<'tcx>,
527 error: InterpErrorInfo<'tcx>,
528 alloc_id: AllocId,
529) -> ErrorHandled {
530 if !#[allow(non_exhaustive_omitted_patterns)] match error.kind() {
InterpErrorKind::UndefinedBehavior(_) => true,
_ => false,
}matches!(error.kind(), InterpErrorKind::UndefinedBehavior(_)) {
531 return report_eval_error(ecx, cid, error);
533 }
534
535 let (error, backtrace) = error.into_parts();
536 backtrace.print_backtrace();
537
538 let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id);
539 let info = ecx.get_alloc_info(alloc_id);
540 let raw_bytes =
541 diagnostics::RawBytesNote { size: info.size.bytes(), align: info.align.bytes(), bytes };
542
543 crate::const_eval::report(ecx, error, move |diag, span, frames| {
544 diag.span_label(span, "it is undefined behavior to use this value");
545 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.");
546 if !frames.is_empty() {
::core::panicking::panic("assertion failed: frames.is_empty()")
};assert!(frames.is_empty()); diag.subdiagnostic(raw_bytes);
548 })
549}