use rustc_errors::{Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
use rustc_macros::{LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::Ty;
use rustc_span::Span;
use crate::rustc::{RustcPatCtxt, WitnessPat};
#[derive(Subdiagnostic)]
#[label(pattern_analysis_uncovered)]
pub struct Uncovered {
#[primary_span]
span: Span,
count: usize,
witness_1: String, witness_2: String, witness_3: String, 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(),
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(LintDiagnostic)]
#[diag(pattern_analysis_overlapping_range_endpoints)]
#[note]
pub struct OverlappingRangeEndpoints {
#[label]
pub range: Span,
#[subdiagnostic]
pub overlap: Vec<Overlap>,
}
pub struct Overlap {
pub span: Span,
pub range: String, }
impl Subdiagnostic for Overlap {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
self,
diag: &mut Diag<'_, G>,
_: &F,
) {
let Overlap { span, range } = self;
let message = format!("this range overlaps on `{range}`...");
diag.span_label(span, message);
}
}
#[derive(LintDiagnostic)]
#[diag(pattern_analysis_excluside_range_missing_max)]
pub struct ExclusiveRangeMissingMax {
#[label]
#[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")]
pub first_range: Span,
pub suggestion: String,
pub max: String, }
#[derive(LintDiagnostic)]
#[diag(pattern_analysis_excluside_range_missing_gap)]
pub struct ExclusiveRangeMissingGap {
#[label]
#[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")]
pub first_range: Span,
pub gap: String, pub suggestion: String,
#[subdiagnostic]
pub gap_with: Vec<GappedRange>,
}
pub struct GappedRange {
pub span: Span,
pub gap: String, pub first_range: String, }
impl Subdiagnostic for GappedRange {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
self,
diag: &mut Diag<'_, G>,
_: &F,
) {
let GappedRange { span, gap, first_range } = self;
let message = format!(
"this could appear to continue range `{first_range}`, but `{gap}` isn't matched by \
either of them"
);
diag.span_label(span, message);
}
}
#[derive(LintDiagnostic)]
#[diag(pattern_analysis_non_exhaustive_omitted_pattern)]
#[help]
#[note]
pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
pub scrut_ty: Ty<'tcx>,
#[subdiagnostic]
pub uncovered: Uncovered,
}
#[derive(LintDiagnostic)]
#[diag(pattern_analysis_non_exhaustive_omitted_pattern_lint_on_arm)]
#[help]
pub(crate) struct NonExhaustiveOmittedPatternLintOnArm {
#[label]
pub lint_span: Span,
#[suggestion(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,
}