1 use crate::thir::pattern::deconstruct_pat::DeconstructedPat;
2 use crate::thir::pattern::MatchCheckCtxt;
3 use rustc_errors::Handler;
5 error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
6 IntoDiagnostic, MultiSpan, SubdiagnosticMessage,
8 use rustc_hir::def::Res;
9 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
10 use rustc_middle::thir::Pat;
11 use rustc_middle::ty::{self, Ty};
12 use rustc_span::{symbol::Ident, Span};
14 #[derive(LintDiagnostic)]
15 #[diag(mir_build_unconditional_recursion)]
17 pub struct UnconditionalRecursion {
20 #[label(mir_build_unconditional_recursion_call_site_label)]
21 pub call_sites: Vec<Span>,
24 #[derive(LintDiagnostic)]
25 #[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe)]
27 pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> {
30 pub function: &'a str,
33 #[derive(LintDiagnostic)]
34 #[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless)]
36 pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
41 #[derive(LintDiagnostic)]
42 #[diag(mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe)]
44 pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
49 #[derive(LintDiagnostic)]
50 #[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe)]
52 pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
57 #[derive(LintDiagnostic)]
58 #[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe)]
60 pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
65 #[derive(LintDiagnostic)]
66 #[diag(mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe)]
68 pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
73 #[derive(LintDiagnostic)]
74 #[diag(mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe)]
76 pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
81 #[derive(LintDiagnostic)]
82 #[diag(mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe)]
84 pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
89 #[derive(LintDiagnostic)]
90 #[diag(mir_build_unsafe_op_in_unsafe_fn_mutation_of_layout_constrained_field_requires_unsafe)]
92 pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
97 #[derive(LintDiagnostic)]
98 #[diag(mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe)]
99 pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
104 #[derive(LintDiagnostic)]
105 #[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe)]
107 pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> {
110 pub function: &'a str,
113 #[derive(Diagnostic)]
114 #[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = "E0133")]
116 pub struct CallToUnsafeFunctionRequiresUnsafe<'a> {
120 pub function: &'a str,
123 #[derive(Diagnostic)]
124 #[diag(mir_build_call_to_unsafe_fn_requires_unsafe_nameless, code = "E0133")]
126 pub struct CallToUnsafeFunctionRequiresUnsafeNameless {
132 #[derive(Diagnostic)]
133 #[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
135 pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> {
139 pub function: &'a str,
142 #[derive(Diagnostic)]
144 mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed,
148 pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed {
154 #[derive(Diagnostic)]
155 #[diag(mir_build_inline_assembly_requires_unsafe, code = "E0133")]
157 pub struct UseOfInlineAssemblyRequiresUnsafe {
163 #[derive(Diagnostic)]
164 #[diag(mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
166 pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
172 #[derive(Diagnostic)]
173 #[diag(mir_build_initializing_type_with_requires_unsafe, code = "E0133")]
175 pub struct InitializingTypeWithRequiresUnsafe {
181 #[derive(Diagnostic)]
183 mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
187 pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
193 #[derive(Diagnostic)]
194 #[diag(mir_build_mutable_static_requires_unsafe, code = "E0133")]
196 pub struct UseOfMutableStaticRequiresUnsafe {
202 #[derive(Diagnostic)]
203 #[diag(mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
205 pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
211 #[derive(Diagnostic)]
212 #[diag(mir_build_extern_static_requires_unsafe, code = "E0133")]
214 pub struct UseOfExternStaticRequiresUnsafe {
220 #[derive(Diagnostic)]
221 #[diag(mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
223 pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
229 #[derive(Diagnostic)]
230 #[diag(mir_build_deref_raw_pointer_requires_unsafe, code = "E0133")]
232 pub struct DerefOfRawPointerRequiresUnsafe {
238 #[derive(Diagnostic)]
239 #[diag(mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
241 pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
247 #[derive(Diagnostic)]
248 #[diag(mir_build_union_field_requires_unsafe, code = "E0133")]
250 pub struct AccessToUnionFieldRequiresUnsafe {
256 #[derive(Diagnostic)]
257 #[diag(mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
259 pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
265 #[derive(Diagnostic)]
266 #[diag(mir_build_mutation_of_layout_constrained_field_requires_unsafe, code = "E0133")]
268 pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe {
274 #[derive(Diagnostic)]
276 mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
280 pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
286 #[derive(Diagnostic)]
287 #[diag(mir_build_borrow_of_layout_constrained_field_requires_unsafe, code = "E0133")]
289 pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe {
295 #[derive(Diagnostic)]
297 mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
301 pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
307 #[derive(Diagnostic)]
308 #[diag(mir_build_call_to_fn_with_requires_unsafe, code = "E0133")]
310 pub struct CallToFunctionWithRequiresUnsafe<'a> {
314 pub function: &'a str,
317 #[derive(Diagnostic)]
318 #[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
320 pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> {
324 pub function: &'a str,
327 #[derive(LintDiagnostic)]
328 #[diag(mir_build_unused_unsafe)]
329 pub struct UnusedUnsafe {
333 pub enclosing: Option<UnusedUnsafeEnclosing>,
336 #[derive(Subdiagnostic)]
337 pub enum UnusedUnsafeEnclosing {
338 #[label(mir_build_unused_unsafe_enclosing_block_label)]
343 #[label(mir_build_unused_unsafe_enclosing_fn_label)]
350 pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> {
351 pub cx: &'m MatchCheckCtxt<'p, 'tcx>,
357 impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
358 fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
359 let mut diag = handler.struct_span_err_with_code(
361 rustc_errors::fluent::mir_build_non_exhaustive_patterns_type_not_empty,
365 let peeled_ty = self.ty.peel_refs();
366 diag.set_arg("ty", self.ty);
367 diag.set_arg("peeled_ty", peeled_ty);
369 if let ty::Adt(def, _) = peeled_ty.kind() {
374 .get_if_local(def.did())
375 .and_then(|node| node.ident())
376 .map(|ident| ident.span)
377 .unwrap_or_else(|| self.cx.tcx.def_span(def.did()));
379 // workaround to make test pass
380 let mut span: MultiSpan = def_span.into();
381 span.push_span_label(def_span, "");
383 diag.span_note(span, rustc_errors::fluent::def_note);
386 let is_variant_list_non_exhaustive = match self.ty.kind() {
387 ty::Adt(def, _) if def.is_variant_list_non_exhaustive() && !def.did().is_local() => {
393 if is_variant_list_non_exhaustive {
394 diag.note(rustc_errors::fluent::non_exhaustive_type_note);
396 diag.note(rustc_errors::fluent::type_note);
399 if let ty::Ref(_, sub_ty, _) = self.ty.kind() {
400 if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.param_env) {
401 diag.note(rustc_errors::fluent::reference_note);
405 let mut suggestion = None;
406 let sm = self.cx.tcx.sess.source_map();
407 if self.span.eq_ctxt(self.expr_span) {
408 // Get the span for the empty match body `{}`.
409 let (indentation, more) = if let Some(snippet) = sm.indentation_before(self.span) {
410 (format!("\n{}", snippet), " ")
412 (" ".to_string(), "")
415 self.span.shrink_to_hi().with_hi(self.expr_span.hi()),
417 " {{{indentation}{more}_ => todo!(),{indentation}}}",
418 indentation = indentation,
424 if let Some((span, sugg)) = suggestion {
425 diag.span_suggestion_verbose(
427 rustc_errors::fluent::suggestion,
429 Applicability::HasPlaceholders,
432 diag.help(rustc_errors::fluent::help);
439 #[derive(Diagnostic)]
440 #[diag(mir_build_static_in_pattern, code = "E0158")]
441 pub struct StaticInPattern {
446 #[derive(Diagnostic)]
447 #[diag(mir_build_assoc_const_in_pattern, code = "E0158")]
448 pub struct AssocConstInPattern {
453 #[derive(Diagnostic)]
454 #[diag(mir_build_const_param_in_pattern, code = "E0158")]
455 pub struct ConstParamInPattern {
460 #[derive(Diagnostic)]
461 #[diag(mir_build_non_const_path, code = "E0080")]
462 pub struct NonConstPath {
467 #[derive(LintDiagnostic)]
468 #[diag(mir_build_unreachable_pattern)]
469 pub struct UnreachablePattern {
471 pub span: Option<Span>,
472 #[label(catchall_label)]
473 pub catchall: Option<Span>,
476 #[derive(Diagnostic)]
477 #[diag(mir_build_const_pattern_depends_on_generic_parameter)]
478 pub struct ConstPatternDependsOnGenericParameter {
483 #[derive(Diagnostic)]
484 #[diag(mir_build_could_not_eval_const_pattern)]
485 pub struct CouldNotEvalConstPattern {
490 #[derive(Diagnostic)]
491 #[diag(mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper, code = "E0030")]
492 pub struct LowerRangeBoundMustBeLessThanOrEqualToUpper {
497 pub teach: Option<()>,
500 #[derive(Diagnostic)]
501 #[diag(mir_build_literal_in_range_out_of_bounds)]
502 pub struct LiteralOutOfRange<'tcx> {
510 #[derive(Diagnostic)]
511 #[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = "E0579")]
512 pub struct LowerRangeBoundMustBeLessThanUpper {
517 #[derive(LintDiagnostic)]
518 #[diag(mir_build_leading_irrefutable_let_patterns)]
521 pub struct LeadingIrrefutableLetPatterns {
525 #[derive(LintDiagnostic)]
526 #[diag(mir_build_trailing_irrefutable_let_patterns)]
529 pub struct TrailingIrrefutableLetPatterns {
533 #[derive(LintDiagnostic)]
534 #[diag(mir_build_bindings_with_variant_name, code = "E0170")]
535 pub struct BindingsWithVariantName {
536 #[suggestion(code = "{ty_path}::{ident}", applicability = "machine-applicable")]
537 pub suggestion: Option<Span>,
542 #[derive(LintDiagnostic)]
543 #[diag(mir_build_irrefutable_let_patterns_generic_let)]
546 pub struct IrrefutableLetPatternsGenericLet {
550 #[derive(LintDiagnostic)]
551 #[diag(mir_build_irrefutable_let_patterns_if_let)]
554 pub struct IrrefutableLetPatternsIfLet {
558 #[derive(LintDiagnostic)]
559 #[diag(mir_build_irrefutable_let_patterns_if_let_guard)]
562 pub struct IrrefutableLetPatternsIfLetGuard {
566 #[derive(LintDiagnostic)]
567 #[diag(mir_build_irrefutable_let_patterns_let_else)]
570 pub struct IrrefutableLetPatternsLetElse {
574 #[derive(LintDiagnostic)]
575 #[diag(mir_build_irrefutable_let_patterns_while_let)]
578 pub struct IrrefutableLetPatternsWhileLet {
582 #[derive(Diagnostic)]
583 #[diag(mir_build_borrow_of_moved_value)]
584 pub struct BorrowOfMovedValue<'tcx> {
588 #[label(occurs_because_label)]
589 pub binding_span: Span,
590 #[label(value_borrowed_label)]
591 pub conflicts_ref: Vec<Span>,
594 #[suggestion(code = "ref ", applicability = "machine-applicable")]
595 pub suggest_borrowing: Option<Span>,
598 #[derive(Diagnostic)]
599 #[diag(mir_build_multiple_mut_borrows)]
600 pub struct MultipleMutBorrows {
604 pub occurences: Vec<Conflict>,
607 #[derive(Diagnostic)]
608 #[diag(mir_build_already_borrowed)]
609 pub struct AlreadyBorrowed {
613 pub occurences: Vec<Conflict>,
616 #[derive(Diagnostic)]
617 #[diag(mir_build_already_mut_borrowed)]
618 pub struct AlreadyMutBorrowed {
622 pub occurences: Vec<Conflict>,
625 #[derive(Diagnostic)]
626 #[diag(mir_build_moved_while_borrowed)]
627 pub struct MovedWhileBorrowed {
631 pub occurences: Vec<Conflict>,
634 #[derive(Subdiagnostic)]
636 #[label(mir_build_mutable_borrow)]
642 #[label(mir_build_borrow)]
648 #[label(mir_build_moved)]
656 #[derive(Diagnostic)]
657 #[diag(mir_build_union_pattern)]
658 pub struct UnionPattern {
663 #[derive(Diagnostic)]
664 #[diag(mir_build_type_not_structural)]
665 pub struct TypeNotStructural<'tcx> {
668 pub non_sm_ty: Ty<'tcx>,
671 #[derive(Diagnostic)]
672 #[diag(mir_build_invalid_pattern)]
673 pub struct InvalidPattern<'tcx> {
676 pub non_sm_ty: Ty<'tcx>,
679 #[derive(Diagnostic)]
680 #[diag(mir_build_unsized_pattern)]
681 pub struct UnsizedPattern<'tcx> {
684 pub non_sm_ty: Ty<'tcx>,
687 #[derive(LintDiagnostic)]
688 #[diag(mir_build_float_pattern)]
689 pub struct FloatPattern;
691 #[derive(LintDiagnostic)]
692 #[diag(mir_build_pointer_pattern)]
693 pub struct PointerPattern;
695 #[derive(LintDiagnostic)]
696 #[diag(mir_build_indirect_structural_match)]
697 pub struct IndirectStructuralMatch<'tcx> {
698 pub non_sm_ty: Ty<'tcx>,
701 #[derive(LintDiagnostic)]
702 #[diag(mir_build_nontrivial_structural_match)]
703 pub struct NontrivialStructuralMatch<'tcx> {
704 pub non_sm_ty: Ty<'tcx>,
707 #[derive(LintDiagnostic)]
708 #[diag(mir_build_overlapping_range_endpoints)]
710 pub struct OverlappingRangeEndpoints<'tcx> {
714 pub overlap: Vec<Overlap<'tcx>>,
717 pub struct Overlap<'tcx> {
719 pub range: Pat<'tcx>,
722 impl<'tcx> AddToDiagnostic for Overlap<'tcx> {
723 fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
725 F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
727 let Overlap { span, range } = self;
729 // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]`
730 // does not support `#[subdiagnostic(eager)]`...
731 let message = format!("this range overlaps on `{range}`...");
732 diag.span_label(span, message);
736 #[derive(LintDiagnostic)]
737 #[diag(mir_build_non_exhaustive_omitted_pattern)]
740 pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
741 pub scrut_ty: Ty<'tcx>,
743 pub uncovered: Uncovered<'tcx>,
746 #[derive(Subdiagnostic)]
747 #[label(mir_build_uncovered)]
748 pub(crate) struct Uncovered<'tcx> {
752 witness_1: Pat<'tcx>,
753 witness_2: Pat<'tcx>,
754 witness_3: Pat<'tcx>,
758 impl<'tcx> Uncovered<'tcx> {
761 cx: &MatchCheckCtxt<'p, 'tcx>,
762 witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
764 let witness_1 = witnesses.get(0).unwrap().to_pat(cx);
767 count: witnesses.len(),
768 // Substitute dummy values if witnesses is smaller than 3. These will never be read.
769 witness_2: witnesses.get(1).map(|w| w.to_pat(cx)).unwrap_or_else(|| witness_1.clone()),
770 witness_3: witnesses.get(2).map(|w| w.to_pat(cx)).unwrap_or_else(|| witness_1.clone()),
772 remainder: witnesses.len().saturating_sub(3),
777 #[derive(Diagnostic)]
778 #[diag(mir_build_pattern_not_covered, code = "E0005")]
779 pub(crate) struct PatternNotCovered<'s, 'tcx> {
784 pub uncovered: Uncovered<'tcx>,
786 pub inform: Option<Inform>,
788 pub interpreted_as_const: Option<InterpretedAsConst>,
790 pub adt_defined_here: Option<AdtDefinedHere<'tcx>>,
793 pub pattern_ty: Ty<'tcx>,
795 pub let_suggestion: Option<SuggestLet>,
797 pub misc_suggestion: Option<MiscPatternSuggestion>,
799 pub res_defined_here: Option<ResDefinedHere>,
802 #[derive(Subdiagnostic)]
803 #[note(mir_build_inform_irrefutable)]
804 #[note(mir_build_more_information)]
807 pub struct AdtDefinedHere<'tcx> {
808 pub adt_def_span: Span,
810 pub variants: Vec<Variant>,
817 impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> {
818 fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
820 F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
822 diag.set_arg("ty", self.ty);
823 let mut spans = MultiSpan::from(self.adt_def_span);
825 for Variant { span } in self.variants {
826 spans.push_span_label(span, rustc_errors::fluent::mir_build_variant_defined_here);
829 diag.span_note(spans, rustc_errors::fluent::mir_build_adt_defined_here);
833 #[derive(Subdiagnostic)]
834 #[label(mir_build_res_defined_here)]
835 pub struct ResDefinedHere {
841 #[derive(Subdiagnostic)]
843 mir_build_interpreted_as_const,
844 code = "{variable}_var",
845 applicability = "maybe-incorrect"
847 #[label(mir_build_confused)]
848 pub struct InterpretedAsConst {
851 pub article: &'static str,
852 pub variable: String,
856 #[derive(Subdiagnostic)]
857 pub enum SuggestLet {
858 #[multipart_suggestion(mir_build_suggest_if_let, applicability = "has-placeholders")]
860 #[suggestion_part(code = "if ")]
862 #[suggestion_part(code = " {{ todo!() }}")]
867 mir_build_suggest_let_else,
868 code = " else {{ todo!() }}",
869 applicability = "has-placeholders"
878 #[derive(Subdiagnostic)]
879 pub enum MiscPatternSuggestion {
881 mir_build_suggest_attempted_int_lit,
883 applicability = "maybe-incorrect"
885 AttemptedIntegerLiteral {