1use std::borrow::Cow;
2use std::fmt::Write;
3
4use either::Either;
5use rustc_abi::WrappingRange;
6use rustc_errors::codes::*;
7use rustc_errors::{
8 Diag, DiagArgValue, DiagMessage, Diagnostic, EmissionGuarantee, Level, MultiSpan, Subdiagnostic,
9};
10use rustc_hir::ConstContext;
11use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
12use rustc_middle::mir::interpret::{
13 CtfeProvenance, ExpectedKind, InterpErrorKind, InvalidMetaKind, InvalidProgramInfo,
14 Misalignment, Pointer, PointerKind, ResourceExhaustionInfo, UndefinedBehaviorInfo,
15 UnsupportedOpInfo, ValidationErrorInfo,
16};
17use rustc_middle::ty::{self, Mutability, Ty};
18use rustc_span::{Span, Symbol};
19
20use crate::fluent_generated as fluent;
21use crate::interpret::InternKind;
22
23#[derive(Diagnostic)]
24#[diag(const_eval_dangling_ptr_in_final)]
25pub(crate) struct DanglingPtrInFinal {
26 #[primary_span]
27 pub span: Span,
28 pub kind: InternKind,
29}
30
31#[derive(Diagnostic)]
32#[diag(const_eval_nested_static_in_thread_local)]
33pub(crate) struct NestedStaticInThreadLocal {
34 #[primary_span]
35 pub span: Span,
36}
37
38#[derive(Diagnostic)]
39#[diag(const_eval_mutable_ptr_in_final)]
40pub(crate) struct MutablePtrInFinal {
41 #[primary_span]
42 pub span: Span,
43 pub kind: InternKind,
44}
45
46#[derive(Diagnostic)]
47#[diag(const_eval_unstable_in_stable_exposed)]
48pub(crate) struct UnstableInStableExposed {
49 pub gate: String,
50 #[primary_span]
51 pub span: Span,
52 #[help(const_eval_is_function_call)]
53 pub is_function_call: bool,
54 pub is_function_call2: bool,
56 #[suggestion(
57 const_eval_unstable_sugg,
58 code = "#[rustc_const_unstable(feature = \"...\", issue = \"...\")]\n",
59 applicability = "has-placeholders"
60 )]
61 pub attr_span: Span,
62}
63
64#[derive(Diagnostic)]
65#[diag(const_eval_thread_local_access, code = E0625)]
66pub(crate) struct ThreadLocalAccessErr {
67 #[primary_span]
68 pub span: Span,
69}
70
71#[derive(Diagnostic)]
72#[diag(const_eval_raw_ptr_to_int)]
73#[note]
74#[note(const_eval_note2)]
75pub(crate) struct RawPtrToIntErr {
76 #[primary_span]
77 pub span: Span,
78}
79
80#[derive(Diagnostic)]
81#[diag(const_eval_raw_ptr_comparison)]
82#[note]
83pub(crate) struct RawPtrComparisonErr {
84 #[primary_span]
85 pub span: Span,
86}
87
88#[derive(Diagnostic)]
89#[diag(const_eval_panic_non_str)]
90pub(crate) struct PanicNonStrErr {
91 #[primary_span]
92 pub span: Span,
93}
94
95#[derive(Diagnostic)]
96#[diag(const_eval_max_num_nodes_in_const)]
97pub(crate) struct MaxNumNodesInConstErr {
98 #[primary_span]
99 pub span: Option<Span>,
100 pub global_const_id: String,
101}
102
103#[derive(Diagnostic)]
104#[diag(const_eval_unallowed_fn_pointer_call)]
105pub(crate) struct UnallowedFnPointerCall {
106 #[primary_span]
107 pub span: Span,
108 pub kind: ConstContext,
109}
110
111#[derive(Diagnostic)]
112#[diag(const_eval_unstable_const_fn)]
113pub(crate) struct UnstableConstFn {
114 #[primary_span]
115 pub span: Span,
116 pub def_path: String,
117}
118
119#[derive(Diagnostic)]
120#[diag(const_eval_unstable_const_trait)]
121pub(crate) struct UnstableConstTrait {
122 #[primary_span]
123 pub span: Span,
124 pub def_path: String,
125}
126
127#[derive(Diagnostic)]
128#[diag(const_eval_unstable_intrinsic)]
129pub(crate) struct UnstableIntrinsic {
130 #[primary_span]
131 pub span: Span,
132 pub name: Symbol,
133 pub feature: Symbol,
134 #[suggestion(
135 const_eval_unstable_intrinsic_suggestion,
136 code = "#![feature({feature})]\n",
137 applicability = "machine-applicable"
138 )]
139 pub suggestion: Option<Span>,
140 #[help(const_eval_unstable_intrinsic_suggestion)]
141 pub help: bool,
142}
143
144#[derive(Diagnostic)]
145#[diag(const_eval_unmarked_const_item_exposed)]
146#[help]
147pub(crate) struct UnmarkedConstItemExposed {
148 #[primary_span]
149 pub span: Span,
150 pub def_path: String,
151}
152
153#[derive(Diagnostic)]
154#[diag(const_eval_unmarked_intrinsic_exposed)]
155#[help]
156pub(crate) struct UnmarkedIntrinsicExposed {
157 #[primary_span]
158 pub span: Span,
159 pub def_path: String,
160}
161
162#[derive(Diagnostic)]
163#[diag(const_eval_mutable_ref_escaping, code = E0764)]
164pub(crate) struct MutableRefEscaping {
165 #[primary_span]
166 pub span: Span,
167 pub kind: ConstContext,
168 #[note(const_eval_teach_note)]
169 pub teach: bool,
170}
171
172#[derive(Diagnostic)]
173#[diag(const_eval_mutable_raw_escaping, code = E0764)]
174pub(crate) struct MutableRawEscaping {
175 #[primary_span]
176 pub span: Span,
177 pub kind: ConstContext,
178 #[note(const_eval_teach_note)]
179 pub teach: bool,
180}
181#[derive(Diagnostic)]
182#[diag(const_eval_non_const_fmt_macro_call, code = E0015)]
183pub(crate) struct NonConstFmtMacroCall {
184 #[primary_span]
185 pub span: Span,
186 pub kind: ConstContext,
187 pub non_or_conditionally: &'static str,
188}
189
190#[derive(Diagnostic)]
191#[diag(const_eval_non_const_fn_call, code = E0015)]
192pub(crate) struct NonConstFnCall {
193 #[primary_span]
194 pub span: Span,
195 pub def_path_str: String,
196 pub def_descr: &'static str,
197 pub kind: ConstContext,
198 pub non_or_conditionally: &'static str,
199}
200
201#[derive(Diagnostic)]
202#[diag(const_eval_non_const_intrinsic)]
203pub(crate) struct NonConstIntrinsic {
204 #[primary_span]
205 pub span: Span,
206 pub name: Symbol,
207 pub kind: ConstContext,
208}
209
210#[derive(Diagnostic)]
211#[diag(const_eval_unallowed_op_in_const_context)]
212pub(crate) struct UnallowedOpInConstContext {
213 #[primary_span]
214 pub span: Span,
215 pub msg: String,
216}
217
218#[derive(Diagnostic)]
219#[diag(const_eval_unallowed_heap_allocations, code = E0010)]
220pub(crate) struct UnallowedHeapAllocations {
221 #[primary_span]
222 #[label]
223 pub span: Span,
224 pub kind: ConstContext,
225 #[note(const_eval_teach_note)]
226 pub teach: bool,
227}
228
229#[derive(Diagnostic)]
230#[diag(const_eval_unallowed_inline_asm, code = E0015)]
231pub(crate) struct UnallowedInlineAsm {
232 #[primary_span]
233 pub span: Span,
234 pub kind: ConstContext,
235}
236
237#[derive(Diagnostic)]
238#[diag(const_eval_interior_mutable_ref_escaping, code = E0492)]
239pub(crate) struct InteriorMutableRefEscaping {
240 #[primary_span]
241 #[label]
242 pub span: Span,
243 #[help]
244 pub opt_help: bool,
245 pub kind: ConstContext,
246 #[note(const_eval_teach_note)]
247 pub teach: bool,
248}
249
250#[derive(LintDiagnostic)]
251#[diag(const_eval_long_running)]
252#[note]
253pub struct LongRunning {
254 #[help]
255 pub item_span: Span,
256}
257
258#[derive(Diagnostic)]
259#[diag(const_eval_long_running)]
260pub struct LongRunningWarn {
261 #[primary_span]
262 #[label]
263 pub span: Span,
264 #[help]
265 pub item_span: Span,
266 pub force_duplicate: usize,
268}
269
270#[derive(Subdiagnostic)]
271#[note(const_eval_non_const_impl)]
272pub(crate) struct NonConstImplNote {
273 #[primary_span]
274 pub span: Span,
275}
276
277#[derive(Clone)]
278pub struct FrameNote {
279 pub span: Span,
280 pub times: i32,
281 pub where_: &'static str,
282 pub instance: String,
283 pub has_label: bool,
284}
285
286impl Subdiagnostic for FrameNote {
287 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
288 diag.arg("times", self.times);
289 diag.arg("where_", self.where_);
290 diag.arg("instance", self.instance);
291 let mut span: MultiSpan = self.span.into();
292 if self.has_label && !self.span.is_dummy() {
293 span.push_span_label(self.span, fluent::const_eval_frame_note_last);
294 }
295 let msg = diag.eagerly_translate(fluent::const_eval_frame_note);
296 diag.span_note(span, msg);
297 }
298}
299
300#[derive(Subdiagnostic)]
301#[note(const_eval_raw_bytes)]
302pub struct RawBytesNote {
303 pub size: u64,
304 pub align: u64,
305 pub bytes: String,
306}
307
308#[derive(Diagnostic)]
311#[diag(const_eval_non_const_match_eq, code = E0015)]
312#[note]
313pub struct NonConstMatchEq<'tcx> {
314 #[primary_span]
315 pub span: Span,
316 pub ty: Ty<'tcx>,
317 pub kind: ConstContext,
318 pub non_or_conditionally: &'static str,
319}
320
321#[derive(Diagnostic)]
322#[diag(const_eval_non_const_for_loop_into_iter, code = E0015)]
323pub struct NonConstForLoopIntoIter<'tcx> {
324 #[primary_span]
325 pub span: Span,
326 pub ty: Ty<'tcx>,
327 pub kind: ConstContext,
328 pub non_or_conditionally: &'static str,
329}
330
331#[derive(Diagnostic)]
332#[diag(const_eval_non_const_question_branch, code = E0015)]
333pub struct NonConstQuestionBranch<'tcx> {
334 #[primary_span]
335 pub span: Span,
336 pub ty: Ty<'tcx>,
337 pub kind: ConstContext,
338 pub non_or_conditionally: &'static str,
339}
340
341#[derive(Diagnostic)]
342#[diag(const_eval_non_const_question_from_residual, code = E0015)]
343pub struct NonConstQuestionFromResidual<'tcx> {
344 #[primary_span]
345 pub span: Span,
346 pub ty: Ty<'tcx>,
347 pub kind: ConstContext,
348 pub non_or_conditionally: &'static str,
349}
350
351#[derive(Diagnostic)]
352#[diag(const_eval_non_const_try_block_from_output, code = E0015)]
353pub struct NonConstTryBlockFromOutput<'tcx> {
354 #[primary_span]
355 pub span: Span,
356 pub ty: Ty<'tcx>,
357 pub kind: ConstContext,
358 pub non_or_conditionally: &'static str,
359}
360
361#[derive(Diagnostic)]
362#[diag(const_eval_non_const_await, code = E0015)]
363pub struct NonConstAwait<'tcx> {
364 #[primary_span]
365 pub span: Span,
366 pub ty: Ty<'tcx>,
367 pub kind: ConstContext,
368 pub non_or_conditionally: &'static str,
369}
370
371#[derive(Diagnostic)]
372#[diag(const_eval_non_const_closure, code = E0015)]
373pub struct NonConstClosure {
374 #[primary_span]
375 pub span: Span,
376 pub kind: ConstContext,
377 #[subdiagnostic]
378 pub note: Option<NonConstClosureNote>,
379 pub non_or_conditionally: &'static str,
380}
381
382#[derive(Subdiagnostic)]
383pub enum NonConstClosureNote {
384 #[note(const_eval_closure_fndef_not_const)]
385 FnDef {
386 #[primary_span]
387 span: Span,
388 },
389 #[note(const_eval_fn_ptr_call)]
390 FnPtr,
391 #[note(const_eval_closure_call)]
392 Closure,
393}
394
395#[derive(Subdiagnostic)]
396#[multipart_suggestion(const_eval_consider_dereferencing, applicability = "machine-applicable")]
397pub struct ConsiderDereferencing {
398 pub deref: String,
399 #[suggestion_part(code = "{deref}")]
400 pub span: Span,
401 #[suggestion_part(code = "{deref}")]
402 pub rhs_span: Span,
403}
404
405#[derive(Diagnostic)]
406#[diag(const_eval_non_const_operator, code = E0015)]
407pub struct NonConstOperator {
408 #[primary_span]
409 pub span: Span,
410 pub kind: ConstContext,
411 #[subdiagnostic]
412 pub sugg: Option<ConsiderDereferencing>,
413 pub non_or_conditionally: &'static str,
414}
415
416#[derive(Diagnostic)]
417#[diag(const_eval_non_const_deref_coercion, code = E0015)]
418#[note]
419pub struct NonConstDerefCoercion<'tcx> {
420 #[primary_span]
421 pub span: Span,
422 pub ty: Ty<'tcx>,
423 pub kind: ConstContext,
424 pub target_ty: Ty<'tcx>,
425 #[note(const_eval_target_note)]
426 pub deref_target: Option<Span>,
427 pub non_or_conditionally: &'static str,
428}
429
430#[derive(Diagnostic)]
431#[diag(const_eval_live_drop, code = E0493)]
432pub struct LiveDrop<'tcx> {
433 #[primary_span]
434 #[label]
435 pub span: Span,
436 pub kind: ConstContext,
437 pub dropped_ty: Ty<'tcx>,
438 #[label(const_eval_dropped_at_label)]
439 pub dropped_at: Span,
440}
441
442pub trait ReportErrorExt {
443 fn diagnostic_message(&self) -> DiagMessage;
445 fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>);
446
447 fn debug(self) -> String
448 where
449 Self: Sized,
450 {
451 ty::tls::with(move |tcx| {
452 let dcx = tcx.dcx();
453 let mut diag = dcx.struct_allow(DiagMessage::Str(String::new().into()));
454 let message = self.diagnostic_message();
455 self.add_args(&mut diag);
456 let s = dcx.eagerly_translate_to_string(message, diag.args.iter());
457 diag.cancel();
458 s
459 })
460 }
461}
462
463impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
464 fn diagnostic_message(&self) -> DiagMessage {
465 use UndefinedBehaviorInfo::*;
466
467 use crate::fluent_generated::*;
468 match self {
469 Ub(msg) => msg.clone().into(),
470 Custom(x) => (x.msg)(),
471 ValidationError(e) => e.diagnostic_message(),
472
473 Unreachable => const_eval_unreachable,
474 BoundsCheckFailed { .. } => const_eval_bounds_check_failed,
475 DivisionByZero => const_eval_division_by_zero,
476 RemainderByZero => const_eval_remainder_by_zero,
477 DivisionOverflow => const_eval_division_overflow,
478 RemainderOverflow => const_eval_remainder_overflow,
479 PointerArithOverflow => const_eval_pointer_arithmetic_overflow,
480 ArithOverflow { .. } => const_eval_overflow_arith,
481 ShiftOverflow { .. } => const_eval_overflow_shift,
482 InvalidMeta(InvalidMetaKind::SliceTooBig) => const_eval_invalid_meta_slice,
483 InvalidMeta(InvalidMetaKind::TooBig) => const_eval_invalid_meta,
484 UnterminatedCString(_) => const_eval_unterminated_c_string,
485 PointerUseAfterFree(_, _) => const_eval_pointer_use_after_free,
486 PointerOutOfBounds { .. } => const_eval_pointer_out_of_bounds,
487 DanglingIntPointer { addr: 0, .. } => const_eval_dangling_null_pointer,
488 DanglingIntPointer { .. } => const_eval_dangling_int_pointer,
489 AlignmentCheckFailed { .. } => const_eval_alignment_check_failed,
490 WriteToReadOnly(_) => const_eval_write_to_read_only,
491 DerefFunctionPointer(_) => const_eval_deref_function_pointer,
492 DerefVTablePointer(_) => const_eval_deref_vtable_pointer,
493 InvalidBool(_) => const_eval_invalid_bool,
494 InvalidChar(_) => const_eval_invalid_char,
495 InvalidTag(_) => const_eval_invalid_tag,
496 InvalidFunctionPointer(_) => const_eval_invalid_function_pointer,
497 InvalidVTablePointer(_) => const_eval_invalid_vtable_pointer,
498 InvalidVTableTrait { .. } => const_eval_invalid_vtable_trait,
499 InvalidStr(_) => const_eval_invalid_str,
500 InvalidUninitBytes(None) => const_eval_invalid_uninit_bytes_unknown,
501 InvalidUninitBytes(Some(_)) => const_eval_invalid_uninit_bytes,
502 DeadLocal => const_eval_dead_local,
503 ScalarSizeMismatch(_) => const_eval_scalar_size_mismatch,
504 UninhabitedEnumVariantWritten(_) => const_eval_uninhabited_enum_variant_written,
505 UninhabitedEnumVariantRead(_) => const_eval_uninhabited_enum_variant_read,
506 InvalidNichedEnumVariantWritten { .. } => {
507 const_eval_invalid_niched_enum_variant_written
508 }
509 AbiMismatchArgument { .. } => const_eval_incompatible_types,
510 AbiMismatchReturn { .. } => const_eval_incompatible_return_types,
511 }
512 }
513
514 fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
515 use UndefinedBehaviorInfo::*;
516 match self {
517 Ub(_) => {}
518 Custom(custom) => {
519 (custom.add_args)(&mut |name, value| {
520 diag.arg(name, value);
521 });
522 }
523 ValidationError(e) => e.add_args(diag),
524
525 Unreachable
526 | DivisionByZero
527 | RemainderByZero
528 | DivisionOverflow
529 | RemainderOverflow
530 | PointerArithOverflow
531 | InvalidMeta(InvalidMetaKind::SliceTooBig)
532 | InvalidMeta(InvalidMetaKind::TooBig)
533 | InvalidUninitBytes(None)
534 | DeadLocal
535 | UninhabitedEnumVariantWritten(_)
536 | UninhabitedEnumVariantRead(_) => {}
537
538 ArithOverflow { intrinsic } => {
539 diag.arg("intrinsic", intrinsic);
540 }
541 ShiftOverflow { intrinsic, shift_amount } => {
542 diag.arg("intrinsic", intrinsic);
543 diag.arg(
544 "shift_amount",
545 match shift_amount {
546 Either::Left(v) => v.to_string(),
547 Either::Right(v) => v.to_string(),
548 },
549 );
550 }
551 BoundsCheckFailed { len, index } => {
552 diag.arg("len", len);
553 diag.arg("index", index);
554 }
555 UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => {
556 diag.arg("pointer", ptr);
557 }
558 InvalidVTableTrait { expected_dyn_type, vtable_dyn_type } => {
559 diag.arg("expected_dyn_type", expected_dyn_type.to_string());
560 diag.arg("vtable_dyn_type", vtable_dyn_type.to_string());
561 }
562 PointerUseAfterFree(alloc_id, msg) => {
563 diag.arg("alloc_id", alloc_id).arg("operation", format!("{:?}", msg));
564 }
565 PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, inbounds_size, msg } => {
566 diag.arg("alloc_size", alloc_size.bytes());
567 diag.arg("pointer", {
568 let mut out = format!("{:?}", alloc_id);
569 if ptr_offset > 0 {
570 write!(out, "+{:#x}", ptr_offset).unwrap();
571 } else if ptr_offset < 0 {
572 write!(out, "-{:#x}", ptr_offset.unsigned_abs()).unwrap();
573 }
574 out
575 });
576 diag.arg("inbounds_size", inbounds_size);
577 diag.arg("inbounds_size_is_neg", inbounds_size < 0);
578 diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs());
579 diag.arg("ptr_offset", ptr_offset);
580 diag.arg("ptr_offset_is_neg", ptr_offset < 0);
581 diag.arg("ptr_offset_abs", ptr_offset.unsigned_abs());
582 diag.arg(
583 "alloc_size_minus_ptr_offset",
584 alloc_size.bytes().saturating_sub(ptr_offset as u64),
585 );
586 diag.arg("operation", format!("{:?}", msg));
587 }
588 DanglingIntPointer { addr, inbounds_size, msg } => {
589 if addr != 0 {
590 diag.arg(
591 "pointer",
592 Pointer::<Option<CtfeProvenance>>::from_addr_invalid(addr).to_string(),
593 );
594 }
595
596 diag.arg("inbounds_size", inbounds_size);
597 diag.arg("inbounds_size_is_neg", inbounds_size < 0);
598 diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs());
599 diag.arg("operation", format!("{:?}", msg));
600 }
601 AlignmentCheckFailed(Misalignment { required, has }, msg) => {
602 diag.arg("required", required.bytes());
603 diag.arg("has", has.bytes());
604 diag.arg("msg", format!("{msg:?}"));
605 }
606 WriteToReadOnly(alloc) | DerefFunctionPointer(alloc) | DerefVTablePointer(alloc) => {
607 diag.arg("allocation", alloc);
608 }
609 InvalidBool(b) => {
610 diag.arg("value", format!("{b:02x}"));
611 }
612 InvalidChar(c) => {
613 diag.arg("value", format!("{c:08x}"));
614 }
615 InvalidTag(tag) => {
616 diag.arg("tag", format!("{tag:x}"));
617 }
618 InvalidStr(err) => {
619 diag.arg("err", format!("{err}"));
620 }
621 InvalidUninitBytes(Some((alloc, info))) => {
622 diag.arg("alloc", alloc);
623 diag.arg("access", info.access);
624 diag.arg("uninit", info.bad);
625 }
626 ScalarSizeMismatch(info) => {
627 diag.arg("target_size", info.target_size);
628 diag.arg("data_size", info.data_size);
629 }
630 InvalidNichedEnumVariantWritten { enum_ty } => {
631 diag.arg("ty", enum_ty.to_string());
632 }
633 AbiMismatchArgument { caller_ty, callee_ty }
634 | AbiMismatchReturn { caller_ty, callee_ty } => {
635 diag.arg("caller_ty", caller_ty.to_string());
636 diag.arg("callee_ty", callee_ty.to_string());
637 }
638 }
639 }
640}
641
642impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
643 fn diagnostic_message(&self) -> DiagMessage {
644 use rustc_middle::mir::interpret::ValidationErrorKind::*;
645
646 use crate::fluent_generated::*;
647 match self.kind {
648 PtrToUninhabited { ptr_kind: PointerKind::Box, .. } => {
649 const_eval_validation_box_to_uninhabited
650 }
651 PtrToUninhabited { ptr_kind: PointerKind::Ref(_), .. } => {
652 const_eval_validation_ref_to_uninhabited
653 }
654
655 PointerAsInt { .. } => const_eval_validation_pointer_as_int,
656 PartialPointer => const_eval_validation_partial_pointer,
657 ConstRefToMutable => const_eval_validation_const_ref_to_mutable,
658 ConstRefToExtern => const_eval_validation_const_ref_to_extern,
659 MutableRefToImmutable => const_eval_validation_mutable_ref_to_immutable,
660 NullFnPtr => const_eval_validation_null_fn_ptr,
661 NeverVal => const_eval_validation_never_val,
662 NullablePtrOutOfRange { .. } => const_eval_validation_nullable_ptr_out_of_range,
663 PtrOutOfRange { .. } => const_eval_validation_ptr_out_of_range,
664 OutOfRange { .. } => const_eval_validation_out_of_range,
665 UnsafeCellInImmutable => const_eval_validation_unsafe_cell,
666 UninhabitedVal { .. } => const_eval_validation_uninhabited_val,
667 InvalidEnumTag { .. } => const_eval_validation_invalid_enum_tag,
668 UninhabitedEnumVariant => const_eval_validation_uninhabited_enum_variant,
669 Uninit { .. } => const_eval_validation_uninit,
670 InvalidVTablePtr { .. } => const_eval_validation_invalid_vtable_ptr,
671 InvalidMetaWrongTrait { .. } => const_eval_validation_invalid_vtable_trait,
672 InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Box } => {
673 const_eval_validation_invalid_box_slice_meta
674 }
675 InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Ref(_) } => {
676 const_eval_validation_invalid_ref_slice_meta
677 }
678
679 InvalidMetaTooLarge { ptr_kind: PointerKind::Box } => {
680 const_eval_validation_invalid_box_meta
681 }
682 InvalidMetaTooLarge { ptr_kind: PointerKind::Ref(_) } => {
683 const_eval_validation_invalid_ref_meta
684 }
685 UnalignedPtr { ptr_kind: PointerKind::Ref(_), .. } => {
686 const_eval_validation_unaligned_ref
687 }
688 UnalignedPtr { ptr_kind: PointerKind::Box, .. } => const_eval_validation_unaligned_box,
689
690 NullPtr { ptr_kind: PointerKind::Box } => const_eval_validation_null_box,
691 NullPtr { ptr_kind: PointerKind::Ref(_) } => const_eval_validation_null_ref,
692 DanglingPtrNoProvenance { ptr_kind: PointerKind::Box, .. } => {
693 const_eval_validation_dangling_box_no_provenance
694 }
695 DanglingPtrNoProvenance { ptr_kind: PointerKind::Ref(_), .. } => {
696 const_eval_validation_dangling_ref_no_provenance
697 }
698 DanglingPtrOutOfBounds { ptr_kind: PointerKind::Box } => {
699 const_eval_validation_dangling_box_out_of_bounds
700 }
701 DanglingPtrOutOfBounds { ptr_kind: PointerKind::Ref(_) } => {
702 const_eval_validation_dangling_ref_out_of_bounds
703 }
704 DanglingPtrUseAfterFree { ptr_kind: PointerKind::Box } => {
705 const_eval_validation_dangling_box_use_after_free
706 }
707 DanglingPtrUseAfterFree { ptr_kind: PointerKind::Ref(_) } => {
708 const_eval_validation_dangling_ref_use_after_free
709 }
710 InvalidBool { .. } => const_eval_validation_invalid_bool,
711 InvalidChar { .. } => const_eval_validation_invalid_char,
712 InvalidFnPtr { .. } => const_eval_validation_invalid_fn_ptr,
713 }
714 }
715
716 fn add_args<G: EmissionGuarantee>(self, err: &mut Diag<'_, G>) {
717 use rustc_middle::mir::interpret::ValidationErrorKind::*;
718
719 use crate::fluent_generated as fluent;
720
721 if let PointerAsInt { .. } | PartialPointer = self.kind {
722 err.help(fluent::const_eval_ptr_as_bytes_1);
723 err.help(fluent::const_eval_ptr_as_bytes_2);
724 }
725
726 let message = if let Some(path) = self.path {
727 err.dcx.eagerly_translate_to_string(
728 fluent::const_eval_validation_front_matter_invalid_value_with_path,
729 [("path".into(), DiagArgValue::Str(path.into()))].iter().map(|(a, b)| (a, b)),
730 )
731 } else {
732 err.dcx.eagerly_translate_to_string(
733 fluent::const_eval_validation_front_matter_invalid_value,
734 [].into_iter(),
735 )
736 };
737
738 err.arg("front_matter", message);
739
740 fn add_range_arg<G: EmissionGuarantee>(
741 r: WrappingRange,
742 max_hi: u128,
743 err: &mut Diag<'_, G>,
744 ) {
745 let WrappingRange { start: lo, end: hi } = r;
746 assert!(hi <= max_hi);
747 let msg = if lo > hi {
748 fluent::const_eval_range_wrapping
749 } else if lo == hi {
750 fluent::const_eval_range_singular
751 } else if lo == 0 {
752 assert!(hi < max_hi, "should not be printing if the range covers everything");
753 fluent::const_eval_range_upper
754 } else if hi == max_hi {
755 assert!(lo > 0, "should not be printing if the range covers everything");
756 fluent::const_eval_range_lower
757 } else {
758 fluent::const_eval_range
759 };
760
761 let args = [
762 ("lo".into(), DiagArgValue::Str(lo.to_string().into())),
763 ("hi".into(), DiagArgValue::Str(hi.to_string().into())),
764 ];
765 let args = args.iter().map(|(a, b)| (a, b));
766 let message = err.dcx.eagerly_translate_to_string(msg, args);
767 err.arg("in_range", message);
768 }
769
770 match self.kind {
771 PtrToUninhabited { ty, .. } | UninhabitedVal { ty } => {
772 err.arg("ty", ty);
773 }
774 PointerAsInt { expected } | Uninit { expected } => {
775 let msg = match expected {
776 ExpectedKind::Reference => fluent::const_eval_validation_expected_ref,
777 ExpectedKind::Box => fluent::const_eval_validation_expected_box,
778 ExpectedKind::RawPtr => fluent::const_eval_validation_expected_raw_ptr,
779 ExpectedKind::InitScalar => fluent::const_eval_validation_expected_init_scalar,
780 ExpectedKind::Bool => fluent::const_eval_validation_expected_bool,
781 ExpectedKind::Char => fluent::const_eval_validation_expected_char,
782 ExpectedKind::Float => fluent::const_eval_validation_expected_float,
783 ExpectedKind::Int => fluent::const_eval_validation_expected_int,
784 ExpectedKind::FnPtr => fluent::const_eval_validation_expected_fn_ptr,
785 ExpectedKind::EnumTag => fluent::const_eval_validation_expected_enum_tag,
786 ExpectedKind::Str => fluent::const_eval_validation_expected_str,
787 };
788 let msg = err.dcx.eagerly_translate_to_string(msg, [].into_iter());
789 err.arg("expected", msg);
790 }
791 InvalidEnumTag { value }
792 | InvalidVTablePtr { value }
793 | InvalidBool { value }
794 | InvalidChar { value }
795 | InvalidFnPtr { value } => {
796 err.arg("value", value);
797 }
798 NullablePtrOutOfRange { range, max_value } | PtrOutOfRange { range, max_value } => {
799 add_range_arg(range, max_value, err)
800 }
801 OutOfRange { range, max_value, value } => {
802 err.arg("value", value);
803 add_range_arg(range, max_value, err);
804 }
805 UnalignedPtr { required_bytes, found_bytes, .. } => {
806 err.arg("required_bytes", required_bytes);
807 err.arg("found_bytes", found_bytes);
808 }
809 DanglingPtrNoProvenance { pointer, .. } => {
810 err.arg("pointer", pointer);
811 }
812 InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type } => {
813 err.arg("vtable_dyn_type", vtable_dyn_type.to_string());
814 err.arg("expected_dyn_type", expected_dyn_type.to_string());
815 }
816 NullPtr { .. }
817 | ConstRefToMutable
818 | ConstRefToExtern
819 | MutableRefToImmutable
820 | NullFnPtr
821 | NeverVal
822 | UnsafeCellInImmutable
823 | InvalidMetaSliceTooLarge { .. }
824 | InvalidMetaTooLarge { .. }
825 | DanglingPtrUseAfterFree { .. }
826 | DanglingPtrOutOfBounds { .. }
827 | UninhabitedEnumVariant
828 | PartialPointer => {}
829 }
830 }
831}
832
833impl ReportErrorExt for UnsupportedOpInfo {
834 fn diagnostic_message(&self) -> DiagMessage {
835 use crate::fluent_generated::*;
836 match self {
837 UnsupportedOpInfo::Unsupported(s) => s.clone().into(),
838 UnsupportedOpInfo::ExternTypeField => const_eval_extern_type_field,
839 UnsupportedOpInfo::UnsizedLocal => const_eval_unsized_local,
840 UnsupportedOpInfo::OverwritePartialPointer(_) => const_eval_partial_pointer_overwrite,
841 UnsupportedOpInfo::ReadPartialPointer(_) => const_eval_partial_pointer_copy,
842 UnsupportedOpInfo::ReadPointerAsInt(_) => const_eval_read_pointer_as_int,
843 UnsupportedOpInfo::ThreadLocalStatic(_) => const_eval_thread_local_static,
844 UnsupportedOpInfo::ExternStatic(_) => const_eval_extern_static,
845 }
846 }
847
848 fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
849 use UnsupportedOpInfo::*;
850
851 use crate::fluent_generated::*;
852 if let ReadPointerAsInt(_) | OverwritePartialPointer(_) | ReadPartialPointer(_) = self {
853 diag.help(const_eval_ptr_as_bytes_1);
854 diag.help(const_eval_ptr_as_bytes_2);
855 }
856 match self {
857 UnsizedLocal
861 | UnsupportedOpInfo::ExternTypeField
862 | Unsupported(_)
863 | ReadPointerAsInt(_) => {}
864 OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => {
865 diag.arg("ptr", ptr);
866 }
867 ThreadLocalStatic(did) | ExternStatic(did) => rustc_middle::ty::tls::with(|tcx| {
868 diag.arg("did", tcx.def_path_str(did));
869 }),
870 }
871 }
872}
873
874impl<'tcx> ReportErrorExt for InterpErrorKind<'tcx> {
875 fn diagnostic_message(&self) -> DiagMessage {
876 match self {
877 InterpErrorKind::UndefinedBehavior(ub) => ub.diagnostic_message(),
878 InterpErrorKind::Unsupported(e) => e.diagnostic_message(),
879 InterpErrorKind::InvalidProgram(e) => e.diagnostic_message(),
880 InterpErrorKind::ResourceExhaustion(e) => e.diagnostic_message(),
881 InterpErrorKind::MachineStop(e) => e.diagnostic_message(),
882 }
883 }
884 fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
885 match self {
886 InterpErrorKind::UndefinedBehavior(ub) => ub.add_args(diag),
887 InterpErrorKind::Unsupported(e) => e.add_args(diag),
888 InterpErrorKind::InvalidProgram(e) => e.add_args(diag),
889 InterpErrorKind::ResourceExhaustion(e) => e.add_args(diag),
890 InterpErrorKind::MachineStop(e) => e.add_args(&mut |name, value| {
891 diag.arg(name, value);
892 }),
893 }
894 }
895}
896
897impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
898 fn diagnostic_message(&self) -> DiagMessage {
899 use crate::fluent_generated::*;
900 match self {
901 InvalidProgramInfo::TooGeneric => const_eval_too_generic,
902 InvalidProgramInfo::AlreadyReported(_) => const_eval_already_reported,
903 InvalidProgramInfo::Layout(e) => e.diagnostic_message(),
904 }
905 }
906 fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
907 match self {
908 InvalidProgramInfo::TooGeneric | InvalidProgramInfo::AlreadyReported(_) => {}
909 InvalidProgramInfo::Layout(e) => {
910 let dummy_level = Level::Bug;
912 let dummy_diag: Diag<'_, ()> = e.into_diagnostic().into_diag(diag.dcx, dummy_level);
913 for (name, val) in dummy_diag.args.iter() {
914 diag.arg(name.clone(), val.clone());
915 }
916 dummy_diag.cancel();
917 }
918 }
919 }
920}
921
922impl ReportErrorExt for ResourceExhaustionInfo {
923 fn diagnostic_message(&self) -> DiagMessage {
924 use crate::fluent_generated::*;
925 match self {
926 ResourceExhaustionInfo::StackFrameLimitReached => const_eval_stack_frame_limit_reached,
927 ResourceExhaustionInfo::MemoryExhausted => const_eval_memory_exhausted,
928 ResourceExhaustionInfo::AddressSpaceFull => const_eval_address_space_full,
929 ResourceExhaustionInfo::Interrupted => const_eval_interrupted,
930 }
931 }
932 fn add_args<G: EmissionGuarantee>(self, _: &mut Diag<'_, G>) {}
933}
934
935impl rustc_errors::IntoDiagArg for InternKind {
936 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
937 DiagArgValue::Str(Cow::Borrowed(match self {
938 InternKind::Static(Mutability::Not) => "static",
939 InternKind::Static(Mutability::Mut) => "static_mut",
940 InternKind::Constant => "const",
941 InternKind::Promoted => "promoted",
942 }))
943 }
944}