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