1use hir::ConstContext;
4use rustc_errors::codes::*;
5use rustc_errors::{Applicability, Diag, MultiSpan, msg};
6use rustc_hir as hir;
7use rustc_hir::attrs::lang_items::LangItem;
8use rustc_hir::def_id::DefId;
9use rustc_infer::infer::TyCtxtInferExt;
10use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
11use rustc_middle::mir::CallSource;
12use rustc_middle::span_bug;
13use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths};
14use rustc_middle::ty::{
15 self, AssocContainer, Closure, FnDef, FnPtr, GenericArgKind, GenericArgsRef, Param, TraitRef,
16 Ty, suggest_constraining_type_param,
17};
18use rustc_session::diagnostics::add_feature_diagnostics;
19use rustc_span::{BytePos, Pos, Span, Symbol, sym};
20use rustc_trait_selection::error_reporting::traits::call_kind::{
21 CallDesugaringKind, CallKind, call_kind,
22};
23use rustc_trait_selection::traits::SelectionContext;
24use tracing::debug;
25
26use super::ConstCx;
27use crate::diagnostics;
28
29#[derive(#[automatically_derived]
impl ::core::clone::Clone for Status {
#[inline]
fn clone(&self) -> Status {
let _: ::core::clone::AssertParamIsClone<Symbol>;
let _: ::core::clone::AssertParamIsClone<bool>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Status { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for Status {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Status::Unstable {
gate: __self_0,
gate_already_checked: __self_1,
safe_to_expose_on_stable: __self_2,
is_function_call: __self_3 } =>
::core::fmt::Formatter::debug_struct_field4_finish(f,
"Unstable", "gate", __self_0, "gate_already_checked",
__self_1, "safe_to_expose_on_stable", __self_2,
"is_function_call", &__self_3),
Status::Forbidden =>
::core::fmt::Formatter::write_str(f, "Forbidden"),
}
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Status {
#[inline]
fn eq(&self, other: &Status) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(Status::Unstable {
gate: __self_0,
gate_already_checked: __self_1,
safe_to_expose_on_stable: __self_2,
is_function_call: __self_3 }, Status::Unstable {
gate: __arg1_0,
gate_already_checked: __arg1_1,
safe_to_expose_on_stable: __arg1_2,
is_function_call: __arg1_3 }) =>
__self_1 == __arg1_1 && __self_2 == __arg1_2 &&
__self_3 == __arg1_3 && __self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Status {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Symbol>;
let _: ::core::cmp::AssertParamIsEq<bool>;
}
}Eq)]
30pub enum Status {
31 Unstable {
32 gate: Symbol,
34 gate_already_checked: bool,
37 safe_to_expose_on_stable: bool,
40 is_function_call: bool,
43 },
44 Forbidden,
45}
46
47#[derive(#[automatically_derived]
impl ::core::clone::Clone for DiagImportance {
#[inline]
fn clone(&self) -> DiagImportance { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for DiagImportance { }Copy)]
48pub enum DiagImportance {
49 Primary,
51
52 Secondary,
54}
55
56pub trait NonConstOp<'tcx>: std::fmt::Debug {
58 fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
60 Status::Forbidden
61 }
62
63 fn importance(&self) -> DiagImportance {
64 DiagImportance::Primary
65 }
66
67 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx>;
68}
69
70#[derive(#[automatically_derived]
impl ::core::fmt::Debug for FnCallIndirect {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "FnCallIndirect")
}
}Debug)]
72pub(crate) struct FnCallIndirect;
73impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
74 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
75 ccx.dcx().create_err(diagnostics::UnallowedFnPointerCall { span, kind: ccx.const_kind() })
76 }
77}
78
79#[derive(#[automatically_derived]
impl ::core::fmt::Debug for FnCallCVariadic {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "FnCallCVariadic")
}
}Debug)]
81pub(crate) struct FnCallCVariadic;
82impl<'tcx> NonConstOp<'tcx> for FnCallCVariadic {
83 fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
84 Status::Unstable {
85 gate: sym::const_c_variadic,
86 gate_already_checked: false,
87 safe_to_expose_on_stable: false,
88 is_function_call: true,
89 }
90 }
91
92 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
93 ccx.tcx.sess.create_feature_err(
94 diagnostics::NonConstCVariadicCall { span, kind: ccx.const_kind() },
95 sym::const_c_variadic,
96 )
97 }
98}
99
100#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for ConditionallyConstCall<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f,
"ConditionallyConstCall", "callee", &self.callee, "args",
&self.args, "span", &self.span, "call_source", &&self.call_source)
}
}Debug)]
102pub(crate) struct ConditionallyConstCall<'tcx> {
103 pub callee: DefId,
104 pub args: GenericArgsRef<'tcx>,
105 pub span: Span,
106 pub call_source: CallSource,
107}
108
109impl<'tcx> NonConstOp<'tcx> for ConditionallyConstCall<'tcx> {
110 fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
111 Status::Unstable {
113 gate: sym::const_trait_impl,
114 gate_already_checked: false,
115 safe_to_expose_on_stable: false,
116 is_function_call: false,
118 }
119 }
120
121 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
122 let mut diag = build_error_for_const_call(
123 ccx,
124 self.callee,
125 self.args,
126 self.span,
127 self.call_source,
128 "conditionally",
129 |_, _, _| {},
130 );
131
132 diag.code(E0658);
134 add_feature_diagnostics(&mut diag, ccx.tcx.sess, sym::const_trait_impl);
135
136 diag
137 }
138}
139
140#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for FnCallNonConst<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f,
"FnCallNonConst", "callee", &self.callee, "args", &self.args,
"span", &self.span, "call_source", &&self.call_source)
}
}Debug, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for FnCallNonConst<'tcx> {
#[inline]
fn clone(&self) -> FnCallNonConst<'tcx> {
let _: ::core::clone::AssertParamIsClone<DefId>;
let _: ::core::clone::AssertParamIsClone<GenericArgsRef<'tcx>>;
let _: ::core::clone::AssertParamIsClone<Span>;
let _: ::core::clone::AssertParamIsClone<CallSource>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for FnCallNonConst<'tcx> { }Copy)]
142pub(crate) struct FnCallNonConst<'tcx> {
143 pub callee: DefId,
144 pub args: GenericArgsRef<'tcx>,
145 pub span: Span,
146 pub call_source: CallSource,
147}
148
149impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
150 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
151 let tcx = ccx.tcx;
152 let caller = ccx.def_id();
153
154 let mut err = build_error_for_const_call(
155 ccx,
156 self.callee,
157 self.args,
158 self.span,
159 self.call_source,
160 "non",
161 |err, self_ty, trait_id| {
162 let trait_ref = TraitRef::from_assoc(tcx, trait_id, self.args);
165
166 match self_ty.kind() {
167 Param(param_ty) => {
168 {
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/check_consts/ops.rs:168",
"rustc_const_eval::check_consts::ops",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/check_consts/ops.rs"),
::tracing_core::__macro_support::Option::Some(168u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::check_consts::ops"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("param_ty")
}> =
::tracing::__macro_support::FieldName::new("param_ty");
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(¶m_ty)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?param_ty);
169 if let Some(generics) = tcx.hir_node_by_def_id(caller).generics() {
170 let constraint = {
let _guard = NoTrimmedGuard::new();
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("[const] {0}",
trait_ref.print_trait_sugared()))
})
}with_no_trimmed_paths!(format!(
171 "[const] {}",
172 trait_ref.print_trait_sugared(),
173 ));
174 suggest_constraining_type_param(
175 tcx,
176 generics,
177 err,
178 param_ty.name.as_str(),
179 &constraint,
180 Some(trait_ref.def_id),
181 None,
182 );
183 }
184 }
185 ty::Adt(..) => {
186 let (infcx, param_env) =
187 tcx.infer_ctxt().build_with_typing_env(ccx.typing_env);
188 let obligation =
189 Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
190 let mut selcx = SelectionContext::new(&infcx);
191 let implsrc = selcx.select(&obligation);
192 if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
193 if !tcx.is_const_trait_impl(data.impl_def_id) {
195 let span = tcx.def_span(data.impl_def_id);
196 err.subdiagnostic(diagnostics::NonConstImplNote { span });
197 }
198 }
199 }
200 _ => {}
201 }
202 },
203 );
204
205 if let ConstContext::Static(_) = ccx.const_kind() {
206 err.note(rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed("consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`"))msg!(
207 "consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`"
208 ));
209 }
210
211 err
212 }
213}
214
215fn build_error_for_const_call<'tcx>(
220 ccx: &ConstCx<'_, 'tcx>,
221 callee: DefId,
222 args: ty::GenericArgsRef<'tcx>,
223 span: Span,
224 call_source: CallSource,
225 non_or_conditionally: &'static str,
226 note_trait_if_possible: impl FnOnce(&mut Diag<'tcx>, Ty<'tcx>, DefId),
227) -> Diag<'tcx> {
228 let tcx = ccx.tcx;
229
230 let call_kind =
231 call_kind(tcx, ccx.typing_env, callee, args, span, call_source.from_hir_call(), None);
232
233 {
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/check_consts/ops.rs:233",
"rustc_const_eval::check_consts::ops",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_const_eval/src/check_consts/ops.rs"),
::tracing_core::__macro_support::Option::Some(233u32),
::tracing_core::__macro_support::Option::Some("rustc_const_eval::check_consts::ops"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("call_kind")
}> =
::tracing::__macro_support::FieldName::new("call_kind");
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(&call_kind)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?call_kind);
234
235 let mut err = match call_kind {
236 CallKind::Normal { desugaring: Some((kind, self_ty)), .. } => {
237 macro_rules! error {
238 ($err:ident) => {
239 tcx.dcx().create_err(diagnostics::$err {
240 span,
241 ty: self_ty,
242 kind: ccx.const_kind(),
243 non_or_conditionally,
244 })
245 };
246 }
247
248 match kind {
251 CallDesugaringKind::ForLoopIntoIter
252 | CallDesugaringKind::ForLoopIntoAsyncIter
253 | CallDesugaringKind::ForLoopNext => {
254 tcx.dcx().create_err(diagnostics::NonConstForLoopIntoIter {
span,
ty: self_ty,
kind: ccx.const_kind(),
non_or_conditionally,
})error!(NonConstForLoopIntoIter)
255 }
256 CallDesugaringKind::QuestionBranch => {
257 tcx.dcx().create_err(diagnostics::NonConstQuestionBranch {
span,
ty: self_ty,
kind: ccx.const_kind(),
non_or_conditionally,
})error!(NonConstQuestionBranch)
258 }
259 CallDesugaringKind::QuestionFromResidual => {
260 tcx.dcx().create_err(diagnostics::NonConstQuestionFromResidual {
span,
ty: self_ty,
kind: ccx.const_kind(),
non_or_conditionally,
})error!(NonConstQuestionFromResidual)
261 }
262 CallDesugaringKind::TryBlockFromOutput => {
263 tcx.dcx().create_err(diagnostics::NonConstTryBlockFromOutput {
span,
ty: self_ty,
kind: ccx.const_kind(),
non_or_conditionally,
})error!(NonConstTryBlockFromOutput)
264 }
265 CallDesugaringKind::Await => {
266 tcx.dcx().create_err(diagnostics::NonConstAwait {
span,
ty: self_ty,
kind: ccx.const_kind(),
non_or_conditionally,
})error!(NonConstAwait)
267 }
268 }
269 }
270 CallKind::FnCall { fn_trait_id, self_ty } => {
271 let kind = ccx.const_kind();
272 let note = match self_ty.kind() {
273 FnDef(def_id, ..) => {
274 let span = tcx.def_span(*def_id);
275 if ccx.tcx.is_const_fn(*def_id) {
276 ::rustc_middle::util::bug::span_bug_fmt(span,
format_args!("calling const FnDef errored when it shouldn\'t"));span_bug!(span, "calling const FnDef errored when it shouldn't");
277 }
278
279 Some(diagnostics::NonConstClosureNote::FnDef { span })
280 }
281 FnPtr(..) => Some(diagnostics::NonConstClosureNote::FnPtr { kind }),
282 Closure(..) => Some(diagnostics::NonConstClosureNote::Closure { kind }),
283 _ => None,
284 };
285
286 let mut err = tcx.dcx().create_err(diagnostics::NonConstClosure {
287 span,
288 kind: ccx.const_kind(),
289 note,
290 non_or_conditionally,
291 });
292
293 note_trait_if_possible(&mut err, self_ty, fn_trait_id);
294 err
295 }
296 CallKind::Operator { trait_id, self_ty, .. } => {
297 let mut err = if let CallSource::MatchCmp = call_source {
298 tcx.dcx().create_err(diagnostics::NonConstMatchEq {
299 span,
300 kind: ccx.const_kind(),
301 ty: self_ty,
302 non_or_conditionally,
303 })
304 } else {
305 let mut sugg = None;
306
307 if ccx.tcx.is_lang_item(trait_id, LangItem::PartialEq) {
308 match (args[0].kind(), args[1].kind()) {
309 (GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
310 if self_ty == rhs_ty
311 && self_ty.is_ref()
312 && self_ty.peel_refs().is_primitive() =>
313 {
314 let mut num_refs = 0;
315 let mut tmp_ty = self_ty;
316 while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
317 num_refs += 1;
318 tmp_ty = *inner_ty;
319 }
320 let deref = "*".repeat(num_refs);
321
322 if let Ok(call_str) = ccx.tcx.sess.source_map().span_to_snippet(span)
323 && let Some(eq_idx) = call_str.find("==")
324 && let Some(rhs_idx) =
325 call_str[(eq_idx + 2)..].find(|c: char| !c.is_whitespace())
326 {
327 let rhs_pos = span.lo() + BytePos::from_usize(eq_idx + 2 + rhs_idx);
328 let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
329 sugg = Some(diagnostics::ConsiderDereferencing {
330 deref,
331 span: span.shrink_to_lo(),
332 rhs_span,
333 });
334 }
335 }
336 _ => {}
337 }
338 }
339 tcx.dcx().create_err(diagnostics::NonConstOperator {
340 span,
341 kind: ccx.const_kind(),
342 sugg,
343 non_or_conditionally,
344 })
345 };
346
347 note_trait_if_possible(&mut err, self_ty, trait_id);
348 err
349 }
350 CallKind::DerefCoercion { deref_target_span, deref_target_ty, self_ty } => {
351 let target = if let Some(deref_target_span) = deref_target_span
353 && tcx.sess.source_map().is_span_accessible(deref_target_span)
354 {
355 Some(deref_target_span)
356 } else {
357 None
358 };
359
360 let mut err = tcx.dcx().create_err(diagnostics::NonConstDerefCoercion {
361 span,
362 ty: self_ty,
363 kind: ccx.const_kind(),
364 target_ty: deref_target_ty,
365 deref_target: target,
366 non_or_conditionally,
367 });
368
369 note_trait_if_possible(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, span));
370 err
371 }
372 _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::FmtArgumentsNew) => {
373 ccx.dcx().create_err(diagnostics::NonConstFmtMacroCall {
374 span,
375 kind: ccx.const_kind(),
376 non_or_conditionally,
377 })
378 }
379 _ => {
380 let def_descr = ccx.tcx.def_descr(callee);
381 let mut err = ccx.dcx().create_err(diagnostics::NonConstFnCall {
382 span,
383 def_descr,
384 def_path_str: ccx.tcx.def_path_str_with_args(callee, args),
385 kind: ccx.const_kind(),
386 non_or_conditionally,
387 });
388 if let Some(item) = ccx.tcx.opt_associated_item(callee) {
389 if let AssocContainer::Trait = item.container
390 && let parent = item.container_id(ccx.tcx)
391 && !ccx.tcx.is_const_trait(parent)
392 {
393 let assoc_span = ccx.tcx.def_span(callee);
394 let assoc_name = ccx.tcx.item_name(callee);
395 let mut span: MultiSpan = ccx.tcx.def_span(parent).into();
396 span.push_span_label(assoc_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this {0} is not const", def_descr))
})format!("this {def_descr} is not const"));
397 let trait_descr = ccx.tcx.def_descr(parent);
398 let trait_span = ccx.tcx.def_span(parent);
399 let trait_name = ccx.tcx.item_name(parent);
400 span.push_span_label(trait_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this {0} is not const",
trait_descr))
})format!("this {trait_descr} is not const"));
401 err.span_note(
402 span,
403 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} `{1}` is not const because {2} `{3}` is not const",
def_descr, assoc_name, trait_descr, trait_name))
})format!(
404 "{def_descr} `{assoc_name}` is not const because {trait_descr} \
405 `{trait_name}` is not const",
406 ),
407 );
408 if let Some(parent) = parent.as_local()
409 && ccx.tcx.sess.is_nightly_build()
410 {
411 if !ccx.tcx.features().const_trait_impl() {
412 err.help(
413 "add `#![feature(const_trait_impl)]` to the crate attributes to \
414 enable const traits",
415 );
416 }
417 let span = ccx.tcx.hir_expect_item(parent).vis_span;
418 let span = ccx.tcx.sess.source_map().span_extend_while_whitespace(span);
419 err.span_suggestion_verbose(
420 span.shrink_to_hi(),
421 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider making trait `{0}` const",
trait_name))
})format!("consider making trait `{trait_name}` const"),
422 "const ".to_owned(),
423 Applicability::MaybeIncorrect,
424 );
425 } else if !ccx.tcx.sess.is_nightly_build() {
426 err.help("const traits are not yet supported on stable Rust");
427 }
428 }
429 } else if !#[allow(non_exhaustive_omitted_patterns)] match ccx.tcx.constness(callee) {
hir::Constness::Const { always: false } => true,
_ => false,
}matches!(ccx.tcx.constness(callee), hir::Constness::Const { always: false })
430 {
431 let name = ccx.tcx.item_name(callee);
432 err.span_note(
433 ccx.tcx.def_span(callee),
434 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} `{1}` is not const", def_descr,
name))
})format!("{def_descr} `{name}` is not const"),
435 );
436 }
437 err
438 }
439 };
440
441 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("calls in {0}s are limited to constant functions, tuple structs and tuple variants",
ccx.const_kind()))
})format!(
442 "calls in {}s are limited to constant functions, tuple structs and tuple variants",
443 ccx.const_kind(),
444 ));
445
446 err
447}
448
449#[derive(#[automatically_derived]
impl ::core::fmt::Debug for CallUnstable {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field5_finish(f, "CallUnstable",
"def_id", &self.def_id, "feature", &self.feature,
"feature_enabled", &self.feature_enabled,
"safe_to_expose_on_stable", &self.safe_to_expose_on_stable,
"is_function_call", &&self.is_function_call)
}
}Debug)]
453pub(crate) struct CallUnstable {
454 pub def_id: DefId,
455 pub feature: Symbol,
456 pub feature_enabled: bool,
459 pub safe_to_expose_on_stable: bool,
460 pub is_function_call: bool,
462}
463
464impl<'tcx> NonConstOp<'tcx> for CallUnstable {
465 fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
466 Status::Unstable {
467 gate: self.feature,
468 gate_already_checked: self.feature_enabled,
469 safe_to_expose_on_stable: self.safe_to_expose_on_stable,
470 is_function_call: self.is_function_call,
471 }
472 }
473
474 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
475 if !!self.feature_enabled {
::core::panicking::panic("assertion failed: !self.feature_enabled")
};assert!(!self.feature_enabled);
476 let mut err = if self.is_function_call {
477 ccx.dcx().create_err(diagnostics::UnstableConstFn {
478 span,
479 def_path: ccx.tcx.def_path_str(self.def_id),
480 })
481 } else {
482 ccx.dcx().create_err(diagnostics::UnstableConstTrait {
483 span,
484 def_path: ccx.tcx.def_path_str(self.def_id),
485 })
486 };
487 ccx.tcx.disabled_nightly_features(&mut err, [(String::new(), self.feature)]);
488 err
489 }
490}
491
492#[derive(#[automatically_derived]
impl ::core::fmt::Debug for IntrinsicNonConst {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"IntrinsicNonConst", "name", &&self.name)
}
}Debug)]
494pub(crate) struct IntrinsicNonConst {
495 pub name: Symbol,
496}
497
498impl<'tcx> NonConstOp<'tcx> for IntrinsicNonConst {
499 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
500 ccx.dcx().create_err(diagnostics::NonConstIntrinsic {
501 span,
502 name: self.name,
503 kind: ccx.const_kind(),
504 })
505 }
506}
507
508#[derive(#[automatically_derived]
impl ::core::fmt::Debug for IntrinsicUnstable {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"IntrinsicUnstable", "name", &self.name, "feature", &self.feature,
"const_stable_indirect", &&self.const_stable_indirect)
}
}Debug)]
510pub(crate) struct IntrinsicUnstable {
511 pub name: Symbol,
512 pub feature: Symbol,
513 pub const_stable_indirect: bool,
514}
515
516impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable {
517 fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
518 Status::Unstable {
519 gate: self.feature,
520 gate_already_checked: false,
521 safe_to_expose_on_stable: self.const_stable_indirect,
522 is_function_call: false,
525 }
526 }
527
528 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
529 ccx.dcx().create_err(diagnostics::UnstableIntrinsic {
530 span,
531 name: self.name,
532 feature: self.feature,
533 suggestion: ccx.tcx.crate_level_attribute_injection_span(),
534 })
535 }
536}
537
538#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Coroutine {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Coroutine",
&&self.0)
}
}Debug)]
539pub(crate) struct Coroutine(pub hir::CoroutineKind);
540impl<'tcx> NonConstOp<'tcx> for Coroutine {
541 fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
542 match self.0 {
543 hir::CoroutineKind::Desugared(
544 hir::CoroutineDesugaring::Async,
545 hir::CoroutineSource::Block,
546 )
547 | hir::CoroutineKind::Coroutine(_) => Status::Unstable {
550 gate: sym::const_async_blocks,
551 gate_already_checked: false,
552 safe_to_expose_on_stable: false,
553 is_function_call: false,
554 },
555 _ => Status::Forbidden,
556 }
557 }
558
559 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
560 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} are not allowed in {1}s",
self.0.to_plural_string(), ccx.const_kind()))
})format!("{} are not allowed in {}s", self.0.to_plural_string(), ccx.const_kind());
561 if let Status::Unstable { gate, .. } = self.status_in_item(ccx) {
562 ccx.tcx
563 .sess
564 .create_feature_err(diagnostics::UnallowedOpInConstContext { span, msg }, gate)
565 } else {
566 ccx.dcx().create_err(diagnostics::UnallowedOpInConstContext { span, msg })
567 }
568 }
569}
570
571#[derive(#[automatically_derived]
impl ::core::fmt::Debug for InlineAsm {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "InlineAsm")
}
}Debug)]
572pub(crate) struct InlineAsm;
573impl<'tcx> NonConstOp<'tcx> for InlineAsm {
574 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
575 ccx.dcx().create_err(diagnostics::UnallowedInlineAsm { span, kind: ccx.const_kind() })
576 }
577}
578
579#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for LiveDrop<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "LiveDrop",
"dropped_at", &self.dropped_at, "dropped_ty", &self.dropped_ty,
"needs_non_const_drop", &&self.needs_non_const_drop)
}
}Debug)]
580pub(crate) struct LiveDrop<'tcx> {
581 pub dropped_at: Span,
582 pub dropped_ty: Ty<'tcx>,
583 pub needs_non_const_drop: bool,
584}
585impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> {
586 fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
587 if self.needs_non_const_drop {
588 Status::Forbidden
589 } else {
590 Status::Unstable {
591 gate: sym::const_destruct,
592 gate_already_checked: false,
593 safe_to_expose_on_stable: false,
594 is_function_call: false,
595 }
596 }
597 }
598
599 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
600 let mut err = if self.needs_non_const_drop {
601 ccx.dcx().create_err(diagnostics::LiveDrop {
602 span,
603 dropped_ty: self.dropped_ty,
604 kind: ccx.const_kind(),
605 dropped_at: self.dropped_at,
606 })
607 } else {
608 ccx.tcx.sess.create_feature_err(
609 diagnostics::LiveDrop {
610 span,
611 dropped_ty: self.dropped_ty,
612 kind: ccx.const_kind(),
613 dropped_at: self.dropped_at,
614 },
615 sym::const_destruct,
616 )
617 };
618
619 if let Param(param_ty) = self.dropped_ty.kind()
622 && ccx.tcx.sess.is_nightly_build()
623 {
624 let tcx = ccx.tcx;
625 let caller = ccx.def_id();
626 if let Some(generics) = tcx.hir_node_by_def_id(caller).generics() {
627 let destruct_def_id = tcx.lang_items().destruct_trait();
628 suggest_constraining_type_param(
629 tcx,
630 generics,
631 &mut err,
632 param_ty.name.as_str(),
633 "[const] Destruct",
634 destruct_def_id,
635 None,
636 );
637 }
638 }
639
640 err
641 }
642}
643
644#[derive(#[automatically_derived]
impl ::core::fmt::Debug for EscapingCellBorrow {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "EscapingCellBorrow")
}
}Debug)]
645pub(crate) struct EscapingCellBorrow;
649impl<'tcx> NonConstOp<'tcx> for EscapingCellBorrow {
650 fn importance(&self) -> DiagImportance {
651 DiagImportance::Secondary
654 }
655 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
656 ccx.dcx()
657 .create_err(diagnostics::InteriorMutableBorrowEscaping { span, kind: ccx.const_kind() })
658 }
659}
660
661#[derive(#[automatically_derived]
impl ::core::fmt::Debug for EscapingMutBorrow {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "EscapingMutBorrow")
}
}Debug)]
662pub(crate) struct EscapingMutBorrow;
666
667impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow {
668 fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
669 Status::Forbidden
670 }
671
672 fn importance(&self) -> DiagImportance {
673 DiagImportance::Secondary
676 }
677
678 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
679 ccx.dcx().create_err(diagnostics::MutableBorrowEscaping { span, kind: ccx.const_kind() })
680 }
681}
682
683#[derive(#[automatically_derived]
impl ::core::fmt::Debug for PanicNonStr {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "PanicNonStr")
}
}Debug)]
685pub(crate) struct PanicNonStr;
686impl<'tcx> NonConstOp<'tcx> for PanicNonStr {
687 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
688 ccx.dcx().create_err(diagnostics::PanicNonStrErr { span })
689 }
690}
691
692#[derive(#[automatically_derived]
impl ::core::fmt::Debug for RawPtrComparison {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "RawPtrComparison")
}
}Debug)]
696pub(crate) struct RawPtrComparison;
697impl<'tcx> NonConstOp<'tcx> for RawPtrComparison {
698 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
699 ccx.dcx().create_err(diagnostics::RawPtrComparisonErr { span })
701 }
702}
703
704#[derive(#[automatically_derived]
impl ::core::fmt::Debug for RawPtrToIntCast {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "RawPtrToIntCast")
}
}Debug)]
708pub(crate) struct RawPtrToIntCast;
709impl<'tcx> NonConstOp<'tcx> for RawPtrToIntCast {
710 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
711 ccx.dcx().create_err(diagnostics::RawPtrToIntErr { span })
712 }
713}
714
715#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ThreadLocalAccess {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "ThreadLocalAccess")
}
}Debug)]
717pub(crate) struct ThreadLocalAccess;
718impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess {
719 fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
720 ccx.dcx().create_err(diagnostics::ThreadLocalAccessErr { span })
721 }
722}