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