| use rustc_macros::{Diagnostic, Subdiagnostic}; | |
| use rustc_middle::ty::Ty; | |
| use rustc_span::Span; | |
| use crate::rustc::{RustcPatCtxt, WitnessPat}; | |
| #[derive(Subdiagnostic)] | |
| #[label( | |
| "{$count -> | |
| [1] pattern `{$witness_1}` | |
| [2] patterns `{$witness_1}` and `{$witness_2}` | |
| [3] patterns `{$witness_1}`, `{$witness_2}` and `{$witness_3}` | |
| *[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more | |
| } not covered" | |
| )] | |
| pub struct Uncovered { | |
| #[primary_span] | |
| span: Span, | |
| count: usize, | |
| witness_1: String, // a printed pattern | |
| witness_2: String, // a printed pattern | |
| witness_3: String, // a printed pattern | |
| remainder: usize, | |
| } | |
| impl Uncovered { | |
| pub fn new<'p, 'tcx>( | |
| span: Span, | |
| cx: &RustcPatCtxt<'p, 'tcx>, | |
| witnesses: Vec<WitnessPat<'p, 'tcx>>, | |
| ) -> Self | |
| where | |
| 'tcx: 'p, | |
| { | |
| let witness_1 = cx.print_witness_pat(witnesses.get(0).unwrap()); | |
| Self { | |
| span, | |
| count: witnesses.len(), | |
| // Substitute dummy values if witnesses is smaller than 3. These will never be read. | |
| witness_2: witnesses.get(1).map(|w| cx.print_witness_pat(w)).unwrap_or_default(), | |
| witness_3: witnesses.get(2).map(|w| cx.print_witness_pat(w)).unwrap_or_default(), | |
| witness_1, | |
| remainder: witnesses.len().saturating_sub(3), | |
| } | |
| } | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("multiple patterns overlap on their endpoints")] | |
| #[note("you likely meant to write mutually exclusive ranges")] | |
| pub(crate) struct OverlappingRangeEndpoints { | |
| #[label("... with this range")] | |
| pub range: Span, | |
| #[subdiagnostic] | |
| pub overlap: Vec<Overlap>, | |
| } | |
| #[derive(Subdiagnostic)] | |
| #[label("this range overlaps on `{$range}`...")] | |
| pub(crate) struct Overlap { | |
| #[primary_span] | |
| pub span: Span, | |
| pub range: String, // a printed pattern | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("exclusive range missing `{$max}`")] | |
| pub(crate) struct ExclusiveRangeMissingMax { | |
| #[label("this range doesn't match `{$max}` because `..` is an exclusive range")] | |
| #[suggestion( | |
| "use an inclusive range instead", | |
| code = "{suggestion}", | |
| applicability = "maybe-incorrect" | |
| )] | |
| /// This is an exclusive range that looks like `lo..max` (i.e. doesn't match `max`). | |
| pub first_range: Span, | |
| /// Suggest `lo..=max` instead. | |
| pub suggestion: String, | |
| pub max: String, // a printed pattern | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("multiple ranges are one apart")] | |
| pub(crate) struct ExclusiveRangeMissingGap { | |
| #[label("this range doesn't match `{$gap}` because `..` is an exclusive range")] | |
| #[suggestion( | |
| "use an inclusive range instead", | |
| code = "{suggestion}", | |
| applicability = "maybe-incorrect" | |
| )] | |
| /// This is an exclusive range that looks like `lo..gap` (i.e. doesn't match `gap`). | |
| pub first_range: Span, | |
| pub gap: String, // a printed pattern | |
| /// Suggest `lo..=gap` instead. | |
| pub suggestion: String, | |
| #[subdiagnostic] | |
| /// All these ranges skipped over `gap` which we think is probably a mistake. | |
| pub gap_with: Vec<GappedRange>, | |
| } | |
| #[derive(Subdiagnostic)] | |
| #[label( | |
| "this could appear to continue range `{$first_range}`, but `{$gap}` isn't matched by either of them" | |
| )] | |
| pub(crate) struct GappedRange { | |
| #[primary_span] | |
| pub span: Span, | |
| pub gap: String, // a printed pattern | |
| pub first_range: String, // a printed pattern | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("some variants are not matched explicitly")] | |
| #[help("ensure that all variants are matched explicitly by adding the suggested match arms")] | |
| #[note( | |
| "the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found" | |
| )] | |
| pub(crate) struct NonExhaustiveOmittedPattern<'tcx> { | |
| pub scrut_ty: Ty<'tcx>, | |
| #[subdiagnostic] | |
| pub uncovered: Uncovered, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("the lint level must be set on the whole match")] | |
| #[help("it no longer has any effect to set the lint level on an individual match arm")] | |
| pub(crate) struct NonExhaustiveOmittedPatternLintOnArm { | |
| #[primary_span] | |
| pub span: Span, | |
| #[label("remove this attribute")] | |
| pub lint_span: Span, | |
| #[suggestion( | |
| "set the lint level on the whole match", | |
| code = "#[{lint_level}({lint_name})]\n", | |
| applicability = "maybe-incorrect" | |
| )] | |
| pub suggest_lint_on_match: Option<Span>, | |
| pub lint_level: &'static str, | |
| pub lint_name: &'static str, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("mix of deref patterns and normal constructors")] | |
| pub(crate) struct MixedDerefPatternConstructors<'tcx> { | |
| #[primary_span] | |
| pub spans: Vec<Span>, | |
| pub smart_pointer_ty: Ty<'tcx>, | |
| #[label("matches on the result of dereferencing `{$smart_pointer_ty}`")] | |
| pub deref_pattern_label: Span, | |
| #[label("matches directly on `{$smart_pointer_ty}`")] | |
| pub normal_constructor_label: Span, | |
| } |