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