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