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 MutableRefInConst => const_eval_validation_mutable_ref_in_const,
669 NullFnPtr => const_eval_validation_null_fn_ptr,
670 NeverVal => const_eval_validation_never_val,
671 NullablePtrOutOfRange { .. } => const_eval_validation_nullable_ptr_out_of_range,
672 PtrOutOfRange { .. } => const_eval_validation_ptr_out_of_range,
673 OutOfRange { .. } => const_eval_validation_out_of_range,
674 UnsafeCellInImmutable => const_eval_validation_unsafe_cell,
675 UninhabitedVal { .. } => const_eval_validation_uninhabited_val,
676 InvalidEnumTag { .. } => const_eval_validation_invalid_enum_tag,
677 UninhabitedEnumVariant => const_eval_validation_uninhabited_enum_variant,
678 Uninit { .. } => const_eval_validation_uninit,
679 InvalidVTablePtr { .. } => const_eval_validation_invalid_vtable_ptr,
680 InvalidMetaWrongTrait { .. } => const_eval_validation_invalid_vtable_trait,
681 InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Box } => {
682 const_eval_validation_invalid_box_slice_meta
683 }
684 InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Ref(_) } => {
685 const_eval_validation_invalid_ref_slice_meta
686 }
687
688 InvalidMetaTooLarge { ptr_kind: PointerKind::Box } => {
689 const_eval_validation_invalid_box_meta
690 }
691 InvalidMetaTooLarge { ptr_kind: PointerKind::Ref(_) } => {
692 const_eval_validation_invalid_ref_meta
693 }
694 UnalignedPtr { ptr_kind: PointerKind::Ref(_), .. } => {
695 const_eval_validation_unaligned_ref
696 }
697 UnalignedPtr { ptr_kind: PointerKind::Box, .. } => const_eval_validation_unaligned_box,
698
699 NullPtr { ptr_kind: PointerKind::Box } => const_eval_validation_null_box,
700 NullPtr { ptr_kind: PointerKind::Ref(_) } => const_eval_validation_null_ref,
701 DanglingPtrNoProvenance { ptr_kind: PointerKind::Box, .. } => {
702 const_eval_validation_dangling_box_no_provenance
703 }
704 DanglingPtrNoProvenance { ptr_kind: PointerKind::Ref(_), .. } => {
705 const_eval_validation_dangling_ref_no_provenance
706 }
707 DanglingPtrOutOfBounds { ptr_kind: PointerKind::Box } => {
708 const_eval_validation_dangling_box_out_of_bounds
709 }
710 DanglingPtrOutOfBounds { ptr_kind: PointerKind::Ref(_) } => {
711 const_eval_validation_dangling_ref_out_of_bounds
712 }
713 DanglingPtrUseAfterFree { ptr_kind: PointerKind::Box } => {
714 const_eval_validation_dangling_box_use_after_free
715 }
716 DanglingPtrUseAfterFree { ptr_kind: PointerKind::Ref(_) } => {
717 const_eval_validation_dangling_ref_use_after_free
718 }
719 InvalidBool { .. } => const_eval_validation_invalid_bool,
720 InvalidChar { .. } => const_eval_validation_invalid_char,
721 InvalidFnPtr { .. } => const_eval_validation_invalid_fn_ptr,
722 }
723 }
724
725 fn add_args<G: EmissionGuarantee>(self, err: &mut Diag<'_, G>) {
726 use rustc_middle::mir::interpret::ValidationErrorKind::*;
727
728 use crate::fluent_generated as fluent;
729
730 if let PointerAsInt { .. } | PartialPointer = self.kind {
731 err.help(fluent::const_eval_ptr_as_bytes_1);
732 err.help(fluent::const_eval_ptr_as_bytes_2);
733 }
734
735 let message = if let Some(path) = self.path {
736 err.dcx.eagerly_translate_to_string(
737 fluent::const_eval_validation_front_matter_invalid_value_with_path,
738 [("path".into(), DiagArgValue::Str(path.into()))].iter().map(|(a, b)| (a, b)),
739 )
740 } else {
741 err.dcx.eagerly_translate_to_string(
742 fluent::const_eval_validation_front_matter_invalid_value,
743 [].into_iter(),
744 )
745 };
746
747 err.arg("front_matter", message);
748
749 fn add_range_arg<G: EmissionGuarantee>(
750 r: WrappingRange,
751 max_hi: u128,
752 err: &mut Diag<'_, G>,
753 ) {
754 let WrappingRange { start: lo, end: hi } = r;
755 assert!(hi <= max_hi);
756 let msg = if lo > hi {
757 fluent::const_eval_range_wrapping
758 } else if lo == hi {
759 fluent::const_eval_range_singular
760 } else if lo == 0 {
761 assert!(hi < max_hi, "should not be printing if the range covers everything");
762 fluent::const_eval_range_upper
763 } else if hi == max_hi {
764 assert!(lo > 0, "should not be printing if the range covers everything");
765 fluent::const_eval_range_lower
766 } else {
767 fluent::const_eval_range
768 };
769
770 let args = [
771 ("lo".into(), DiagArgValue::Str(lo.to_string().into())),
772 ("hi".into(), DiagArgValue::Str(hi.to_string().into())),
773 ];
774 let args = args.iter().map(|(a, b)| (a, b));
775 let message = err.dcx.eagerly_translate_to_string(msg, args);
776 err.arg("in_range", message);
777 }
778
779 match self.kind {
780 PtrToUninhabited { ty, .. } | UninhabitedVal { ty } => {
781 err.arg("ty", ty);
782 }
783 PointerAsInt { expected } | Uninit { expected } => {
784 let msg = match expected {
785 ExpectedKind::Reference => fluent::const_eval_validation_expected_ref,
786 ExpectedKind::Box => fluent::const_eval_validation_expected_box,
787 ExpectedKind::RawPtr => fluent::const_eval_validation_expected_raw_ptr,
788 ExpectedKind::InitScalar => fluent::const_eval_validation_expected_init_scalar,
789 ExpectedKind::Bool => fluent::const_eval_validation_expected_bool,
790 ExpectedKind::Char => fluent::const_eval_validation_expected_char,
791 ExpectedKind::Float => fluent::const_eval_validation_expected_float,
792 ExpectedKind::Int => fluent::const_eval_validation_expected_int,
793 ExpectedKind::FnPtr => fluent::const_eval_validation_expected_fn_ptr,
794 ExpectedKind::EnumTag => fluent::const_eval_validation_expected_enum_tag,
795 ExpectedKind::Str => fluent::const_eval_validation_expected_str,
796 };
797 let msg = err.dcx.eagerly_translate_to_string(msg, [].into_iter());
798 err.arg("expected", msg);
799 }
800 InvalidEnumTag { value }
801 | InvalidVTablePtr { value }
802 | InvalidBool { value }
803 | InvalidChar { value }
804 | InvalidFnPtr { value } => {
805 err.arg("value", value);
806 }
807 NullablePtrOutOfRange { range, max_value } | PtrOutOfRange { range, max_value } => {
808 add_range_arg(range, max_value, err)
809 }
810 OutOfRange { range, max_value, value } => {
811 err.arg("value", value);
812 add_range_arg(range, max_value, err);
813 }
814 UnalignedPtr { required_bytes, found_bytes, .. } => {
815 err.arg("required_bytes", required_bytes);
816 err.arg("found_bytes", found_bytes);
817 }
818 DanglingPtrNoProvenance { pointer, .. } => {
819 err.arg("pointer", pointer);
820 }
821 InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type } => {
822 err.arg("vtable_dyn_type", vtable_dyn_type.to_string());
823 err.arg("expected_dyn_type", expected_dyn_type.to_string());
824 }
825 NullPtr { .. }
826 | MutableRefToImmutable
827 | MutableRefInConst
828 | NullFnPtr
829 | NeverVal
830 | UnsafeCellInImmutable
831 | InvalidMetaSliceTooLarge { .. }
832 | InvalidMetaTooLarge { .. }
833 | DanglingPtrUseAfterFree { .. }
834 | DanglingPtrOutOfBounds { .. }
835 | UninhabitedEnumVariant
836 | PartialPointer => {}
837 }
838 }
839}
840
841impl ReportErrorExt for UnsupportedOpInfo {
842 fn diagnostic_message(&self) -> DiagMessage {
843 use crate::fluent_generated::*;
844 match self {
845 UnsupportedOpInfo::Unsupported(s) => s.clone().into(),
846 UnsupportedOpInfo::ExternTypeField => const_eval_extern_type_field,
847 UnsupportedOpInfo::UnsizedLocal => const_eval_unsized_local,
848 UnsupportedOpInfo::ReadPartialPointer(_) => const_eval_partial_pointer_read,
849 UnsupportedOpInfo::ReadPointerAsInt(_) => const_eval_read_pointer_as_int,
850 UnsupportedOpInfo::ThreadLocalStatic(_) => const_eval_thread_local_static,
851 UnsupportedOpInfo::ExternStatic(_) => const_eval_extern_static,
852 }
853 }
854
855 fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
856 use UnsupportedOpInfo::*;
857
858 use crate::fluent_generated::*;
859 if let ReadPointerAsInt(_) | ReadPartialPointer(_) = self {
860 diag.help(const_eval_ptr_as_bytes_1);
861 diag.help(const_eval_ptr_as_bytes_2);
862 }
863 match self {
864 UnsizedLocal
868 | UnsupportedOpInfo::ExternTypeField
869 | Unsupported(_)
870 | ReadPointerAsInt(_) => {}
871 ReadPartialPointer(ptr) => {
872 diag.arg("ptr", ptr);
873 }
874 ThreadLocalStatic(did) | ExternStatic(did) => rustc_middle::ty::tls::with(|tcx| {
875 diag.arg("did", tcx.def_path_str(did));
876 }),
877 }
878 }
879}
880
881impl<'tcx> ReportErrorExt for InterpErrorKind<'tcx> {
882 fn diagnostic_message(&self) -> DiagMessage {
883 match self {
884 InterpErrorKind::UndefinedBehavior(ub) => ub.diagnostic_message(),
885 InterpErrorKind::Unsupported(e) => e.diagnostic_message(),
886 InterpErrorKind::InvalidProgram(e) => e.diagnostic_message(),
887 InterpErrorKind::ResourceExhaustion(e) => e.diagnostic_message(),
888 InterpErrorKind::MachineStop(e) => e.diagnostic_message(),
889 }
890 }
891 fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
892 match self {
893 InterpErrorKind::UndefinedBehavior(ub) => ub.add_args(diag),
894 InterpErrorKind::Unsupported(e) => e.add_args(diag),
895 InterpErrorKind::InvalidProgram(e) => e.add_args(diag),
896 InterpErrorKind::ResourceExhaustion(e) => e.add_args(diag),
897 InterpErrorKind::MachineStop(e) => e.add_args(&mut |name, value| {
898 diag.arg(name, value);
899 }),
900 }
901 }
902}
903
904impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
905 fn diagnostic_message(&self) -> DiagMessage {
906 use crate::fluent_generated::*;
907 match self {
908 InvalidProgramInfo::TooGeneric => const_eval_too_generic,
909 InvalidProgramInfo::AlreadyReported(_) => const_eval_already_reported,
910 InvalidProgramInfo::Layout(e) => e.diagnostic_message(),
911 }
912 }
913 fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
914 match self {
915 InvalidProgramInfo::TooGeneric | InvalidProgramInfo::AlreadyReported(_) => {}
916 InvalidProgramInfo::Layout(e) => {
917 let dummy_level = Level::Bug;
919 let dummy_diag: Diag<'_, ()> = e.into_diagnostic().into_diag(diag.dcx, dummy_level);
920 for (name, val) in dummy_diag.args.iter() {
921 diag.arg(name.clone(), val.clone());
922 }
923 dummy_diag.cancel();
924 }
925 }
926 }
927}
928
929impl ReportErrorExt for ResourceExhaustionInfo {
930 fn diagnostic_message(&self) -> DiagMessage {
931 use crate::fluent_generated::*;
932 match self {
933 ResourceExhaustionInfo::StackFrameLimitReached => const_eval_stack_frame_limit_reached,
934 ResourceExhaustionInfo::MemoryExhausted => const_eval_memory_exhausted,
935 ResourceExhaustionInfo::AddressSpaceFull => const_eval_address_space_full,
936 ResourceExhaustionInfo::Interrupted => const_eval_interrupted,
937 }
938 }
939 fn add_args<G: EmissionGuarantee>(self, _: &mut Diag<'_, G>) {}
940}
941
942impl rustc_errors::IntoDiagArg for InternKind {
943 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
944 DiagArgValue::Str(Cow::Borrowed(match self {
945 InternKind::Static(Mutability::Not) => "static",
946 InternKind::Static(Mutability::Mut) => "static_mut",
947 InternKind::Constant => "const",
948 InternKind::Promoted => "promoted",
949 }))
950 }
951}