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