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, SubdiagMessageOp, 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_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
294 self,
295 diag: &mut Diag<'_, G>,
296 f: &F,
297 ) {
298 diag.arg("times", self.times);
299 diag.arg("where_", self.where_);
300 diag.arg("instance", self.instance);
301 let mut span: MultiSpan = self.span.into();
302 if self.has_label && !self.span.is_dummy() {
303 span.push_span_label(self.span, fluent::const_eval_frame_note_last);
304 }
305 let msg = f(diag, fluent::const_eval_frame_note.into());
306 diag.span_note(span, msg);
307 }
308}
309
310#[derive(Subdiagnostic)]
311#[note(const_eval_raw_bytes)]
312pub struct RawBytesNote {
313 pub size: u64,
314 pub align: u64,
315 pub bytes: String,
316}
317
318#[derive(Diagnostic)]
321#[diag(const_eval_non_const_match_eq, code = E0015)]
322#[note]
323pub struct NonConstMatchEq<'tcx> {
324 #[primary_span]
325 pub span: Span,
326 pub ty: Ty<'tcx>,
327 pub kind: ConstContext,
328 pub non_or_conditionally: &'static str,
329}
330
331#[derive(Diagnostic)]
332#[diag(const_eval_non_const_for_loop_into_iter, code = E0015)]
333pub struct NonConstForLoopIntoIter<'tcx> {
334 #[primary_span]
335 pub span: Span,
336 pub ty: Ty<'tcx>,
337 pub kind: ConstContext,
338 pub non_or_conditionally: &'static str,
339}
340
341#[derive(Diagnostic)]
342#[diag(const_eval_non_const_question_branch, code = E0015)]
343pub struct NonConstQuestionBranch<'tcx> {
344 #[primary_span]
345 pub span: Span,
346 pub ty: Ty<'tcx>,
347 pub kind: ConstContext,
348 pub non_or_conditionally: &'static str,
349}
350
351#[derive(Diagnostic)]
352#[diag(const_eval_non_const_question_from_residual, code = E0015)]
353pub struct NonConstQuestionFromResidual<'tcx> {
354 #[primary_span]
355 pub span: Span,
356 pub ty: Ty<'tcx>,
357 pub kind: ConstContext,
358 pub non_or_conditionally: &'static str,
359}
360
361#[derive(Diagnostic)]
362#[diag(const_eval_non_const_try_block_from_output, code = E0015)]
363pub struct NonConstTryBlockFromOutput<'tcx> {
364 #[primary_span]
365 pub span: Span,
366 pub ty: Ty<'tcx>,
367 pub kind: ConstContext,
368 pub non_or_conditionally: &'static str,
369}
370
371#[derive(Diagnostic)]
372#[diag(const_eval_non_const_await, code = E0015)]
373pub struct NonConstAwait<'tcx> {
374 #[primary_span]
375 pub span: Span,
376 pub ty: Ty<'tcx>,
377 pub kind: ConstContext,
378 pub non_or_conditionally: &'static str,
379}
380
381#[derive(Diagnostic)]
382#[diag(const_eval_non_const_closure, code = E0015)]
383pub struct NonConstClosure {
384 #[primary_span]
385 pub span: Span,
386 pub kind: ConstContext,
387 #[subdiagnostic]
388 pub note: Option<NonConstClosureNote>,
389 pub non_or_conditionally: &'static str,
390}
391
392#[derive(Subdiagnostic)]
393pub enum NonConstClosureNote {
394 #[note(const_eval_closure_fndef_not_const)]
395 FnDef {
396 #[primary_span]
397 span: Span,
398 },
399 #[note(const_eval_fn_ptr_call)]
400 FnPtr,
401 #[note(const_eval_closure_call)]
402 Closure,
403}
404
405#[derive(Subdiagnostic)]
406#[multipart_suggestion(const_eval_consider_dereferencing, applicability = "machine-applicable")]
407pub struct ConsiderDereferencing {
408 pub deref: String,
409 #[suggestion_part(code = "{deref}")]
410 pub span: Span,
411 #[suggestion_part(code = "{deref}")]
412 pub rhs_span: Span,
413}
414
415#[derive(Diagnostic)]
416#[diag(const_eval_non_const_operator, code = E0015)]
417pub struct NonConstOperator {
418 #[primary_span]
419 pub span: Span,
420 pub kind: ConstContext,
421 #[subdiagnostic]
422 pub sugg: Option<ConsiderDereferencing>,
423 pub non_or_conditionally: &'static str,
424}
425
426#[derive(Diagnostic)]
427#[diag(const_eval_non_const_deref_coercion, code = E0015)]
428#[note]
429pub struct NonConstDerefCoercion<'tcx> {
430 #[primary_span]
431 pub span: Span,
432 pub ty: Ty<'tcx>,
433 pub kind: ConstContext,
434 pub target_ty: Ty<'tcx>,
435 #[note(const_eval_target_note)]
436 pub deref_target: Option<Span>,
437 pub non_or_conditionally: &'static str,
438}
439
440#[derive(Diagnostic)]
441#[diag(const_eval_live_drop, code = E0493)]
442pub struct LiveDrop<'tcx> {
443 #[primary_span]
444 #[label]
445 pub span: Span,
446 pub kind: ConstContext,
447 pub dropped_ty: Ty<'tcx>,
448 #[label(const_eval_dropped_at_label)]
449 pub dropped_at: Span,
450}
451
452#[derive(Diagnostic)]
453#[diag(const_eval_error, code = E0080)]
454pub struct ConstEvalError {
455 #[primary_span]
456 pub span: Span,
457 pub error_kind: &'static str,
459 pub instance: String,
460 #[subdiagnostic]
461 pub frame_notes: Vec<FrameNote>,
462}
463
464#[derive(Diagnostic)]
465#[diag(const_eval_nullary_intrinsic_fail)]
466pub struct NullaryIntrinsicError {
467 #[primary_span]
468 pub span: Span,
469}
470
471#[derive(Diagnostic)]
472#[diag(const_eval_validation_failure, code = E0080)]
473pub struct ValidationFailure {
474 #[primary_span]
475 pub span: Span,
476 #[note(const_eval_validation_failure_note)]
477 pub ub_note: (),
478 #[subdiagnostic]
479 pub frames: Vec<FrameNote>,
480 #[subdiagnostic]
481 pub raw_bytes: RawBytesNote,
482}
483
484pub trait ReportErrorExt {
485 fn diagnostic_message(&self) -> DiagMessage;
487 fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>);
488
489 fn debug(self) -> String
490 where
491 Self: Sized,
492 {
493 ty::tls::with(move |tcx| {
494 let dcx = tcx.dcx();
495 let mut diag = dcx.struct_allow(DiagMessage::Str(String::new().into()));
496 let message = self.diagnostic_message();
497 self.add_args(&mut diag);
498 let s = dcx.eagerly_translate_to_string(message, diag.args.iter());
499 diag.cancel();
500 s
501 })
502 }
503}
504
505fn bad_pointer_message(msg: CheckInAllocMsg, dcx: DiagCtxtHandle<'_>) -> String {
506 use crate::fluent_generated::*;
507
508 let msg = match msg {
509 CheckInAllocMsg::MemoryAccessTest => const_eval_memory_access_test,
510 CheckInAllocMsg::PointerArithmeticTest => const_eval_pointer_arithmetic_test,
511 CheckInAllocMsg::OffsetFromTest => const_eval_offset_from_test,
512 CheckInAllocMsg::InboundsTest => const_eval_in_bounds_test,
513 };
514
515 dcx.eagerly_translate_to_string(msg, [].into_iter())
516}
517
518impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
519 fn diagnostic_message(&self) -> DiagMessage {
520 use UndefinedBehaviorInfo::*;
521
522 use crate::fluent_generated::*;
523 match self {
524 Ub(msg) => msg.clone().into(),
525 Custom(x) => (x.msg)(),
526 ValidationError(e) => e.diagnostic_message(),
527
528 Unreachable => const_eval_unreachable,
529 BoundsCheckFailed { .. } => const_eval_bounds_check_failed,
530 DivisionByZero => const_eval_division_by_zero,
531 RemainderByZero => const_eval_remainder_by_zero,
532 DivisionOverflow => const_eval_division_overflow,
533 RemainderOverflow => const_eval_remainder_overflow,
534 PointerArithOverflow => const_eval_pointer_arithmetic_overflow,
535 ArithOverflow { .. } => const_eval_overflow_arith,
536 ShiftOverflow { .. } => const_eval_overflow_shift,
537 InvalidMeta(InvalidMetaKind::SliceTooBig) => const_eval_invalid_meta_slice,
538 InvalidMeta(InvalidMetaKind::TooBig) => const_eval_invalid_meta,
539 UnterminatedCString(_) => const_eval_unterminated_c_string,
540 PointerUseAfterFree(_, _) => const_eval_pointer_use_after_free,
541 PointerOutOfBounds { .. } => const_eval_pointer_out_of_bounds,
542 DanglingIntPointer { addr: 0, .. } => const_eval_dangling_null_pointer,
543 DanglingIntPointer { .. } => const_eval_dangling_int_pointer,
544 AlignmentCheckFailed { .. } => const_eval_alignment_check_failed,
545 WriteToReadOnly(_) => const_eval_write_to_read_only,
546 DerefFunctionPointer(_) => const_eval_deref_function_pointer,
547 DerefVTablePointer(_) => const_eval_deref_vtable_pointer,
548 InvalidBool(_) => const_eval_invalid_bool,
549 InvalidChar(_) => const_eval_invalid_char,
550 InvalidTag(_) => const_eval_invalid_tag,
551 InvalidFunctionPointer(_) => const_eval_invalid_function_pointer,
552 InvalidVTablePointer(_) => const_eval_invalid_vtable_pointer,
553 InvalidVTableTrait { .. } => const_eval_invalid_vtable_trait,
554 InvalidStr(_) => const_eval_invalid_str,
555 InvalidUninitBytes(None) => const_eval_invalid_uninit_bytes_unknown,
556 InvalidUninitBytes(Some(_)) => const_eval_invalid_uninit_bytes,
557 DeadLocal => const_eval_dead_local,
558 ScalarSizeMismatch(_) => const_eval_scalar_size_mismatch,
559 UninhabitedEnumVariantWritten(_) => const_eval_uninhabited_enum_variant_written,
560 UninhabitedEnumVariantRead(_) => const_eval_uninhabited_enum_variant_read,
561 InvalidNichedEnumVariantWritten { .. } => {
562 const_eval_invalid_niched_enum_variant_written
563 }
564 AbiMismatchArgument { .. } => const_eval_incompatible_types,
565 AbiMismatchReturn { .. } => const_eval_incompatible_return_types,
566 }
567 }
568
569 fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
570 use UndefinedBehaviorInfo::*;
571 let dcx = diag.dcx;
572 match self {
573 Ub(_) => {}
574 Custom(custom) => {
575 (custom.add_args)(&mut |name, value| {
576 diag.arg(name, value);
577 });
578 }
579 ValidationError(e) => e.add_args(diag),
580
581 Unreachable
582 | DivisionByZero
583 | RemainderByZero
584 | DivisionOverflow
585 | RemainderOverflow
586 | PointerArithOverflow
587 | InvalidMeta(InvalidMetaKind::SliceTooBig)
588 | InvalidMeta(InvalidMetaKind::TooBig)
589 | InvalidUninitBytes(None)
590 | DeadLocal
591 | UninhabitedEnumVariantWritten(_)
592 | UninhabitedEnumVariantRead(_) => {}
593
594 ArithOverflow { intrinsic } => {
595 diag.arg("intrinsic", intrinsic);
596 }
597 ShiftOverflow { intrinsic, shift_amount } => {
598 diag.arg("intrinsic", intrinsic);
599 diag.arg(
600 "shift_amount",
601 match shift_amount {
602 Either::Left(v) => v.to_string(),
603 Either::Right(v) => v.to_string(),
604 },
605 );
606 }
607 BoundsCheckFailed { len, index } => {
608 diag.arg("len", len);
609 diag.arg("index", index);
610 }
611 UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => {
612 diag.arg("pointer", ptr);
613 }
614 InvalidVTableTrait { expected_dyn_type, vtable_dyn_type } => {
615 diag.arg("expected_dyn_type", expected_dyn_type.to_string());
616 diag.arg("vtable_dyn_type", vtable_dyn_type.to_string());
617 }
618 PointerUseAfterFree(alloc_id, msg) => {
619 diag.arg("alloc_id", alloc_id)
620 .arg("bad_pointer_message", bad_pointer_message(msg, dcx));
621 }
622 PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, inbounds_size, msg } => {
623 diag.arg("alloc_size", alloc_size.bytes());
624 diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
625 diag.arg("pointer", {
626 let mut out = format!("{:?}", alloc_id);
627 if ptr_offset > 0 {
628 write!(out, "+{:#x}", ptr_offset).unwrap();
629 } else if ptr_offset < 0 {
630 write!(out, "-{:#x}", ptr_offset.unsigned_abs()).unwrap();
631 }
632 out
633 });
634 diag.arg("inbounds_size_is_neg", inbounds_size < 0);
635 diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs());
636 diag.arg("ptr_offset_is_neg", ptr_offset < 0);
637 diag.arg("ptr_offset_abs", ptr_offset.unsigned_abs());
638 diag.arg(
639 "alloc_size_minus_ptr_offset",
640 alloc_size.bytes().saturating_sub(ptr_offset as u64),
641 );
642 }
643 DanglingIntPointer { addr, inbounds_size, msg } => {
644 if addr != 0 {
645 diag.arg(
646 "pointer",
647 Pointer::<Option<CtfeProvenance>>::from_addr_invalid(addr).to_string(),
648 );
649 }
650
651 diag.arg("inbounds_size_is_neg", inbounds_size < 0);
652 diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs());
653 diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
654 }
655 AlignmentCheckFailed(Misalignment { required, has }, msg) => {
656 diag.arg("required", required.bytes());
657 diag.arg("has", has.bytes());
658 diag.arg("msg", format!("{msg:?}"));
659 }
660 WriteToReadOnly(alloc) | DerefFunctionPointer(alloc) | DerefVTablePointer(alloc) => {
661 diag.arg("allocation", alloc);
662 }
663 InvalidBool(b) => {
664 diag.arg("value", format!("{b:02x}"));
665 }
666 InvalidChar(c) => {
667 diag.arg("value", format!("{c:08x}"));
668 }
669 InvalidTag(tag) => {
670 diag.arg("tag", format!("{tag:x}"));
671 }
672 InvalidStr(err) => {
673 diag.arg("err", format!("{err}"));
674 }
675 InvalidUninitBytes(Some((alloc, info))) => {
676 diag.arg("alloc", alloc);
677 diag.arg("access", info.access);
678 diag.arg("uninit", info.bad);
679 }
680 ScalarSizeMismatch(info) => {
681 diag.arg("target_size", info.target_size);
682 diag.arg("data_size", info.data_size);
683 }
684 InvalidNichedEnumVariantWritten { enum_ty } => {
685 diag.arg("ty", enum_ty.to_string());
686 }
687 AbiMismatchArgument { caller_ty, callee_ty }
688 | AbiMismatchReturn { caller_ty, callee_ty } => {
689 diag.arg("caller_ty", caller_ty.to_string());
690 diag.arg("callee_ty", callee_ty.to_string());
691 }
692 }
693 }
694}
695
696impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
697 fn diagnostic_message(&self) -> DiagMessage {
698 use rustc_middle::mir::interpret::ValidationErrorKind::*;
699
700 use crate::fluent_generated::*;
701 match self.kind {
702 PtrToUninhabited { ptr_kind: PointerKind::Box, .. } => {
703 const_eval_validation_box_to_uninhabited
704 }
705 PtrToUninhabited { ptr_kind: PointerKind::Ref(_), .. } => {
706 const_eval_validation_ref_to_uninhabited
707 }
708
709 PointerAsInt { .. } => const_eval_validation_pointer_as_int,
710 PartialPointer => const_eval_validation_partial_pointer,
711 ConstRefToMutable => const_eval_validation_const_ref_to_mutable,
712 ConstRefToExtern => const_eval_validation_const_ref_to_extern,
713 MutableRefToImmutable => const_eval_validation_mutable_ref_to_immutable,
714 NullFnPtr => const_eval_validation_null_fn_ptr,
715 NeverVal => const_eval_validation_never_val,
716 NullablePtrOutOfRange { .. } => const_eval_validation_nullable_ptr_out_of_range,
717 PtrOutOfRange { .. } => const_eval_validation_ptr_out_of_range,
718 OutOfRange { .. } => const_eval_validation_out_of_range,
719 UnsafeCellInImmutable => const_eval_validation_unsafe_cell,
720 UninhabitedVal { .. } => const_eval_validation_uninhabited_val,
721 InvalidEnumTag { .. } => const_eval_validation_invalid_enum_tag,
722 UninhabitedEnumVariant => const_eval_validation_uninhabited_enum_variant,
723 Uninit { .. } => const_eval_validation_uninit,
724 InvalidVTablePtr { .. } => const_eval_validation_invalid_vtable_ptr,
725 InvalidMetaWrongTrait { .. } => const_eval_validation_invalid_vtable_trait,
726 InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Box } => {
727 const_eval_validation_invalid_box_slice_meta
728 }
729 InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Ref(_) } => {
730 const_eval_validation_invalid_ref_slice_meta
731 }
732
733 InvalidMetaTooLarge { ptr_kind: PointerKind::Box } => {
734 const_eval_validation_invalid_box_meta
735 }
736 InvalidMetaTooLarge { ptr_kind: PointerKind::Ref(_) } => {
737 const_eval_validation_invalid_ref_meta
738 }
739 UnalignedPtr { ptr_kind: PointerKind::Ref(_), .. } => {
740 const_eval_validation_unaligned_ref
741 }
742 UnalignedPtr { ptr_kind: PointerKind::Box, .. } => const_eval_validation_unaligned_box,
743
744 NullPtr { ptr_kind: PointerKind::Box } => const_eval_validation_null_box,
745 NullPtr { ptr_kind: PointerKind::Ref(_) } => const_eval_validation_null_ref,
746 DanglingPtrNoProvenance { ptr_kind: PointerKind::Box, .. } => {
747 const_eval_validation_dangling_box_no_provenance
748 }
749 DanglingPtrNoProvenance { ptr_kind: PointerKind::Ref(_), .. } => {
750 const_eval_validation_dangling_ref_no_provenance
751 }
752 DanglingPtrOutOfBounds { ptr_kind: PointerKind::Box } => {
753 const_eval_validation_dangling_box_out_of_bounds
754 }
755 DanglingPtrOutOfBounds { ptr_kind: PointerKind::Ref(_) } => {
756 const_eval_validation_dangling_ref_out_of_bounds
757 }
758 DanglingPtrUseAfterFree { ptr_kind: PointerKind::Box } => {
759 const_eval_validation_dangling_box_use_after_free
760 }
761 DanglingPtrUseAfterFree { ptr_kind: PointerKind::Ref(_) } => {
762 const_eval_validation_dangling_ref_use_after_free
763 }
764 InvalidBool { .. } => const_eval_validation_invalid_bool,
765 InvalidChar { .. } => const_eval_validation_invalid_char,
766 InvalidFnPtr { .. } => const_eval_validation_invalid_fn_ptr,
767 }
768 }
769
770 fn add_args<G: EmissionGuarantee>(self, err: &mut Diag<'_, G>) {
771 use rustc_middle::mir::interpret::ValidationErrorKind::*;
772
773 use crate::fluent_generated as fluent;
774
775 if let PointerAsInt { .. } | PartialPointer = self.kind {
776 err.help(fluent::const_eval_ptr_as_bytes_1);
777 err.help(fluent::const_eval_ptr_as_bytes_2);
778 }
779
780 let message = if let Some(path) = self.path {
781 err.dcx.eagerly_translate_to_string(
782 fluent::const_eval_validation_front_matter_invalid_value_with_path,
783 [("path".into(), DiagArgValue::Str(path.into()))].iter().map(|(a, b)| (a, b)),
784 )
785 } else {
786 err.dcx.eagerly_translate_to_string(
787 fluent::const_eval_validation_front_matter_invalid_value,
788 [].into_iter(),
789 )
790 };
791
792 err.arg("front_matter", message);
793
794 fn add_range_arg<G: EmissionGuarantee>(
795 r: WrappingRange,
796 max_hi: u128,
797 err: &mut Diag<'_, G>,
798 ) {
799 let WrappingRange { start: lo, end: hi } = r;
800 assert!(hi <= max_hi);
801 let msg = if lo > hi {
802 fluent::const_eval_range_wrapping
803 } else if lo == hi {
804 fluent::const_eval_range_singular
805 } else if lo == 0 {
806 assert!(hi < max_hi, "should not be printing if the range covers everything");
807 fluent::const_eval_range_upper
808 } else if hi == max_hi {
809 assert!(lo > 0, "should not be printing if the range covers everything");
810 fluent::const_eval_range_lower
811 } else {
812 fluent::const_eval_range
813 };
814
815 let args = [
816 ("lo".into(), DiagArgValue::Str(lo.to_string().into())),
817 ("hi".into(), DiagArgValue::Str(hi.to_string().into())),
818 ];
819 let args = args.iter().map(|(a, b)| (a, b));
820 let message = err.dcx.eagerly_translate_to_string(msg, args);
821 err.arg("in_range", message);
822 }
823
824 match self.kind {
825 PtrToUninhabited { ty, .. } | UninhabitedVal { ty } => {
826 err.arg("ty", ty);
827 }
828 PointerAsInt { expected } | Uninit { expected } => {
829 let msg = match expected {
830 ExpectedKind::Reference => fluent::const_eval_validation_expected_ref,
831 ExpectedKind::Box => fluent::const_eval_validation_expected_box,
832 ExpectedKind::RawPtr => fluent::const_eval_validation_expected_raw_ptr,
833 ExpectedKind::InitScalar => fluent::const_eval_validation_expected_init_scalar,
834 ExpectedKind::Bool => fluent::const_eval_validation_expected_bool,
835 ExpectedKind::Char => fluent::const_eval_validation_expected_char,
836 ExpectedKind::Float => fluent::const_eval_validation_expected_float,
837 ExpectedKind::Int => fluent::const_eval_validation_expected_int,
838 ExpectedKind::FnPtr => fluent::const_eval_validation_expected_fn_ptr,
839 ExpectedKind::EnumTag => fluent::const_eval_validation_expected_enum_tag,
840 ExpectedKind::Str => fluent::const_eval_validation_expected_str,
841 };
842 let msg = err.dcx.eagerly_translate_to_string(msg, [].into_iter());
843 err.arg("expected", msg);
844 }
845 InvalidEnumTag { value }
846 | InvalidVTablePtr { value }
847 | InvalidBool { value }
848 | InvalidChar { value }
849 | InvalidFnPtr { value } => {
850 err.arg("value", value);
851 }
852 NullablePtrOutOfRange { range, max_value } | PtrOutOfRange { range, max_value } => {
853 add_range_arg(range, max_value, err)
854 }
855 OutOfRange { range, max_value, value } => {
856 err.arg("value", value);
857 add_range_arg(range, max_value, err);
858 }
859 UnalignedPtr { required_bytes, found_bytes, .. } => {
860 err.arg("required_bytes", required_bytes);
861 err.arg("found_bytes", found_bytes);
862 }
863 DanglingPtrNoProvenance { pointer, .. } => {
864 err.arg("pointer", pointer);
865 }
866 InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type } => {
867 err.arg("vtable_dyn_type", vtable_dyn_type.to_string());
868 err.arg("expected_dyn_type", expected_dyn_type.to_string());
869 }
870 NullPtr { .. }
871 | ConstRefToMutable
872 | ConstRefToExtern
873 | MutableRefToImmutable
874 | NullFnPtr
875 | NeverVal
876 | UnsafeCellInImmutable
877 | InvalidMetaSliceTooLarge { .. }
878 | InvalidMetaTooLarge { .. }
879 | DanglingPtrUseAfterFree { .. }
880 | DanglingPtrOutOfBounds { .. }
881 | UninhabitedEnumVariant
882 | PartialPointer => {}
883 }
884 }
885}
886
887impl ReportErrorExt for UnsupportedOpInfo {
888 fn diagnostic_message(&self) -> DiagMessage {
889 use crate::fluent_generated::*;
890 match self {
891 UnsupportedOpInfo::Unsupported(s) => s.clone().into(),
892 UnsupportedOpInfo::ExternTypeField => const_eval_extern_type_field,
893 UnsupportedOpInfo::UnsizedLocal => const_eval_unsized_local,
894 UnsupportedOpInfo::OverwritePartialPointer(_) => const_eval_partial_pointer_overwrite,
895 UnsupportedOpInfo::ReadPartialPointer(_) => const_eval_partial_pointer_copy,
896 UnsupportedOpInfo::ReadPointerAsInt(_) => const_eval_read_pointer_as_int,
897 UnsupportedOpInfo::ThreadLocalStatic(_) => const_eval_thread_local_static,
898 UnsupportedOpInfo::ExternStatic(_) => const_eval_extern_static,
899 }
900 }
901
902 fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
903 use UnsupportedOpInfo::*;
904
905 use crate::fluent_generated::*;
906 if let ReadPointerAsInt(_) | OverwritePartialPointer(_) | ReadPartialPointer(_) = self {
907 diag.help(const_eval_ptr_as_bytes_1);
908 diag.help(const_eval_ptr_as_bytes_2);
909 }
910 match self {
911 UnsizedLocal
915 | UnsupportedOpInfo::ExternTypeField
916 | Unsupported(_)
917 | ReadPointerAsInt(_) => {}
918 OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => {
919 diag.arg("ptr", ptr);
920 }
921 ThreadLocalStatic(did) | ExternStatic(did) => rustc_middle::ty::tls::with(|tcx| {
922 diag.arg("did", tcx.def_path_str(did));
923 }),
924 }
925 }
926}
927
928impl<'tcx> ReportErrorExt for InterpErrorKind<'tcx> {
929 fn diagnostic_message(&self) -> DiagMessage {
930 match self {
931 InterpErrorKind::UndefinedBehavior(ub) => ub.diagnostic_message(),
932 InterpErrorKind::Unsupported(e) => e.diagnostic_message(),
933 InterpErrorKind::InvalidProgram(e) => e.diagnostic_message(),
934 InterpErrorKind::ResourceExhaustion(e) => e.diagnostic_message(),
935 InterpErrorKind::MachineStop(e) => e.diagnostic_message(),
936 }
937 }
938 fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
939 match self {
940 InterpErrorKind::UndefinedBehavior(ub) => ub.add_args(diag),
941 InterpErrorKind::Unsupported(e) => e.add_args(diag),
942 InterpErrorKind::InvalidProgram(e) => e.add_args(diag),
943 InterpErrorKind::ResourceExhaustion(e) => e.add_args(diag),
944 InterpErrorKind::MachineStop(e) => e.add_args(&mut |name, value| {
945 diag.arg(name, value);
946 }),
947 }
948 }
949}
950
951impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
952 fn diagnostic_message(&self) -> DiagMessage {
953 use crate::fluent_generated::*;
954 match self {
955 InvalidProgramInfo::TooGeneric => const_eval_too_generic,
956 InvalidProgramInfo::AlreadyReported(_) => const_eval_already_reported,
957 InvalidProgramInfo::Layout(e) => e.diagnostic_message(),
958 }
959 }
960 fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
961 match self {
962 InvalidProgramInfo::TooGeneric | InvalidProgramInfo::AlreadyReported(_) => {}
963 InvalidProgramInfo::Layout(e) => {
964 let dummy_level = Level::Bug;
966 let dummy_diag: Diag<'_, ()> = e.into_diagnostic().into_diag(diag.dcx, dummy_level);
967 for (name, val) in dummy_diag.args.iter() {
968 diag.arg(name.clone(), val.clone());
969 }
970 dummy_diag.cancel();
971 }
972 }
973 }
974}
975
976impl ReportErrorExt for ResourceExhaustionInfo {
977 fn diagnostic_message(&self) -> DiagMessage {
978 use crate::fluent_generated::*;
979 match self {
980 ResourceExhaustionInfo::StackFrameLimitReached => const_eval_stack_frame_limit_reached,
981 ResourceExhaustionInfo::MemoryExhausted => const_eval_memory_exhausted,
982 ResourceExhaustionInfo::AddressSpaceFull => const_eval_address_space_full,
983 ResourceExhaustionInfo::Interrupted => const_eval_interrupted,
984 }
985 }
986 fn add_args<G: EmissionGuarantee>(self, _: &mut Diag<'_, G>) {}
987}
988
989impl rustc_errors::IntoDiagArg for InternKind {
990 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
991 DiagArgValue::Str(Cow::Borrowed(match self {
992 InternKind::Static(Mutability::Not) => "static",
993 InternKind::Static(Mutability::Mut) => "static_mut",
994 InternKind::Constant => "const",
995 InternKind::Promoted => "promoted",
996 }))
997 }
998}