rustc_pattern_analysis/
errors.rs
1use rustc_errors::{Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
2use rustc_macros::{LintDiagnostic, Subdiagnostic};
3use rustc_middle::ty::Ty;
4use rustc_span::Span;
5
6use crate::rustc::{RustcPatCtxt, WitnessPat};
7
8#[derive(Subdiagnostic)]
9#[label(pattern_analysis_uncovered)]
10pub struct Uncovered {
11 #[primary_span]
12 span: Span,
13 count: usize,
14 witness_1: String, witness_2: String, witness_3: String, remainder: usize,
18}
19
20impl Uncovered {
21 pub fn new<'p, 'tcx>(
22 span: Span,
23 cx: &RustcPatCtxt<'p, 'tcx>,
24 witnesses: Vec<WitnessPat<'p, 'tcx>>,
25 ) -> Self
26 where
27 'tcx: 'p,
28 {
29 let witness_1 = cx.print_witness_pat(witnesses.get(0).unwrap());
30 Self {
31 span,
32 count: witnesses.len(),
33 witness_2: witnesses.get(1).map(|w| cx.print_witness_pat(w)).unwrap_or_default(),
35 witness_3: witnesses.get(2).map(|w| cx.print_witness_pat(w)).unwrap_or_default(),
36 witness_1,
37 remainder: witnesses.len().saturating_sub(3),
38 }
39 }
40}
41
42#[derive(LintDiagnostic)]
43#[diag(pattern_analysis_overlapping_range_endpoints)]
44#[note]
45pub struct OverlappingRangeEndpoints {
46 #[label]
47 pub range: Span,
48 #[subdiagnostic]
49 pub overlap: Vec<Overlap>,
50}
51
52pub struct Overlap {
53 pub span: Span,
54 pub range: String, }
56
57impl Subdiagnostic for Overlap {
58 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
59 self,
60 diag: &mut Diag<'_, G>,
61 _: &F,
62 ) {
63 let Overlap { span, range } = self;
64
65 let message = format!("this range overlaps on `{range}`...");
68 diag.span_label(span, message);
69 }
70}
71
72#[derive(LintDiagnostic)]
73#[diag(pattern_analysis_excluside_range_missing_max)]
74pub struct ExclusiveRangeMissingMax {
75 #[label]
76 #[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")]
77 pub first_range: Span,
79 pub suggestion: String,
81 pub max: String, }
83
84#[derive(LintDiagnostic)]
85#[diag(pattern_analysis_excluside_range_missing_gap)]
86pub struct ExclusiveRangeMissingGap {
87 #[label]
88 #[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")]
89 pub first_range: Span,
91 pub gap: String, pub suggestion: String,
94 #[subdiagnostic]
95 pub gap_with: Vec<GappedRange>,
97}
98
99pub struct GappedRange {
100 pub span: Span,
101 pub gap: String, pub first_range: String, }
104
105impl Subdiagnostic for GappedRange {
106 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
107 self,
108 diag: &mut Diag<'_, G>,
109 _: &F,
110 ) {
111 let GappedRange { span, gap, first_range } = self;
112
113 let message = format!(
116 "this could appear to continue range `{first_range}`, but `{gap}` isn't matched by \
117 either of them"
118 );
119 diag.span_label(span, message);
120 }
121}
122
123#[derive(LintDiagnostic)]
124#[diag(pattern_analysis_non_exhaustive_omitted_pattern)]
125#[help]
126#[note]
127pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
128 pub scrut_ty: Ty<'tcx>,
129 #[subdiagnostic]
130 pub uncovered: Uncovered,
131}
132
133#[derive(LintDiagnostic)]
134#[diag(pattern_analysis_non_exhaustive_omitted_pattern_lint_on_arm)]
135#[help]
136pub(crate) struct NonExhaustiveOmittedPatternLintOnArm {
137 #[label]
138 pub lint_span: Span,
139 #[suggestion(code = "#[{lint_level}({lint_name})]\n", applicability = "maybe-incorrect")]
140 pub suggest_lint_on_match: Option<Span>,
141 pub lint_level: &'static str,
142 pub lint_name: &'static str,
143}