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