2024-02-06 05:35:19 +00:00
|
|
|
use rustc_errors::{AddToDiagnostic, Diagnostic, SubdiagnosticMessageOp};
|
2023-12-10 19:42:30 +00:00
|
|
|
use rustc_macros::{LintDiagnostic, Subdiagnostic};
|
|
|
|
use rustc_middle::thir::Pat;
|
|
|
|
use rustc_middle::ty::Ty;
|
|
|
|
use rustc_span::Span;
|
|
|
|
|
2023-12-14 16:54:11 +00:00
|
|
|
use crate::rustc::{RustcMatchCheckCtxt, WitnessPat};
|
2023-12-11 19:01:02 +00:00
|
|
|
|
2023-12-10 19:42:30 +00:00
|
|
|
#[derive(Subdiagnostic)]
|
|
|
|
#[label(pattern_analysis_uncovered)]
|
|
|
|
pub struct Uncovered<'tcx> {
|
|
|
|
#[primary_span]
|
|
|
|
span: Span,
|
|
|
|
count: usize,
|
|
|
|
witness_1: Pat<'tcx>,
|
|
|
|
witness_2: Pat<'tcx>,
|
|
|
|
witness_3: Pat<'tcx>,
|
|
|
|
remainder: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> Uncovered<'tcx> {
|
|
|
|
pub fn new<'p>(
|
|
|
|
span: Span,
|
2023-12-14 16:54:11 +00:00
|
|
|
cx: &RustcMatchCheckCtxt<'p, 'tcx>,
|
2023-12-11 19:01:02 +00:00
|
|
|
witnesses: Vec<WitnessPat<'p, 'tcx>>,
|
2024-01-25 03:35:09 +00:00
|
|
|
) -> Self
|
|
|
|
where
|
|
|
|
'tcx: 'p,
|
|
|
|
{
|
2023-12-10 21:14:00 +00:00
|
|
|
let witness_1 = cx.hoist_witness_pat(witnesses.get(0).unwrap());
|
2023-12-10 19:42:30 +00:00
|
|
|
Self {
|
|
|
|
span,
|
|
|
|
count: witnesses.len(),
|
|
|
|
// Substitute dummy values if witnesses is smaller than 3. These will never be read.
|
|
|
|
witness_2: witnesses
|
|
|
|
.get(1)
|
2023-12-10 21:14:00 +00:00
|
|
|
.map(|w| cx.hoist_witness_pat(w))
|
2023-12-10 19:42:30 +00:00
|
|
|
.unwrap_or_else(|| witness_1.clone()),
|
|
|
|
witness_3: witnesses
|
|
|
|
.get(2)
|
2023-12-10 21:14:00 +00:00
|
|
|
.map(|w| cx.hoist_witness_pat(w))
|
2023-12-10 19:42:30 +00:00
|
|
|
.unwrap_or_else(|| witness_1.clone()),
|
|
|
|
witness_1,
|
|
|
|
remainder: witnesses.len().saturating_sub(3),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(LintDiagnostic)]
|
|
|
|
#[diag(pattern_analysis_overlapping_range_endpoints)]
|
|
|
|
#[note]
|
|
|
|
pub struct OverlappingRangeEndpoints<'tcx> {
|
|
|
|
#[label]
|
|
|
|
pub range: Span,
|
|
|
|
#[subdiagnostic]
|
|
|
|
pub overlap: Vec<Overlap<'tcx>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Overlap<'tcx> {
|
|
|
|
pub span: Span,
|
|
|
|
pub range: Pat<'tcx>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> AddToDiagnostic for Overlap<'tcx> {
|
2024-02-06 05:35:19 +00:00
|
|
|
fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) {
|
2023-12-10 19:42:30 +00:00
|
|
|
let Overlap { span, range } = self;
|
|
|
|
|
|
|
|
// FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]`
|
|
|
|
// does not support `#[subdiagnostic(eager)]`...
|
|
|
|
let message = format!("this range overlaps on `{range}`...");
|
|
|
|
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<'tcx>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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,
|
|
|
|
}
|