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