2024-03-06 03:00:16 +00:00
|
|
|
use rustc_errors::{Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
|
2023-12-10 19:42:30 +00:00
|
|
|
use rustc_macros::{LintDiagnostic, Subdiagnostic};
|
|
|
|
use rustc_middle::ty::Ty;
|
|
|
|
use rustc_span::Span;
|
|
|
|
|
2024-03-13 13:07:44 +00:00
|
|
|
use crate::rustc::{RustcPatCtxt, WitnessPat};
|
2023-12-11 19:01:02 +00:00
|
|
|
|
2023-12-10 19:42:30 +00:00
|
|
|
#[derive(Subdiagnostic)]
|
|
|
|
#[label(pattern_analysis_uncovered)]
|
2024-07-28 05:12:14 +00:00
|
|
|
pub struct Uncovered {
|
2023-12-10 19:42:30 +00:00
|
|
|
#[primary_span]
|
|
|
|
span: Span,
|
|
|
|
count: usize,
|
2024-07-28 05:12:14 +00:00
|
|
|
witness_1: String, // a printed pattern
|
|
|
|
witness_2: String, // a printed pattern
|
|
|
|
witness_3: String, // a printed pattern
|
2023-12-10 19:42:30 +00:00
|
|
|
remainder: usize,
|
|
|
|
}
|
|
|
|
|
2024-07-28 05:12:14 +00:00
|
|
|
impl Uncovered {
|
|
|
|
pub fn new<'p, 'tcx>(
|
2023-12-10 19:42:30 +00:00
|
|
|
span: Span,
|
2024-03-13 13:07:44 +00:00
|
|
|
cx: &RustcPatCtxt<'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,
|
|
|
|
{
|
2024-07-28 05:14:26 +00:00
|
|
|
let witness_1 = cx.print_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.
|
2024-07-28 05:14:26 +00:00
|
|
|
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(),
|
2023-12-10 19:42:30 +00:00
|
|
|
witness_1,
|
|
|
|
remainder: witnesses.len().saturating_sub(3),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(LintDiagnostic)]
|
|
|
|
#[diag(pattern_analysis_overlapping_range_endpoints)]
|
|
|
|
#[note]
|
2024-07-28 05:12:14 +00:00
|
|
|
pub struct OverlappingRangeEndpoints {
|
2023-12-10 19:42:30 +00:00
|
|
|
#[label]
|
|
|
|
pub range: Span,
|
|
|
|
#[subdiagnostic]
|
2024-07-28 05:12:14 +00:00
|
|
|
pub overlap: Vec<Overlap>,
|
2023-12-10 19:42:30 +00:00
|
|
|
}
|
|
|
|
|
2024-07-28 05:12:14 +00:00
|
|
|
pub struct Overlap {
|
2023-12-10 19:42:30 +00:00
|
|
|
pub span: Span,
|
2024-07-28 05:12:14 +00:00
|
|
|
pub range: String, // a printed pattern
|
2023-12-10 19:42:30 +00:00
|
|
|
}
|
|
|
|
|
2024-07-28 05:12:14 +00:00
|
|
|
impl Subdiagnostic for Overlap {
|
2024-03-06 03:00:16 +00:00
|
|
|
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
Reduce capabilities of `Diagnostic`.
Currently many diagnostic modifier methods are available on both
`Diagnostic` and `DiagnosticBuilder`. This commit removes most of them
from `Diagnostic`. To minimize the diff size, it keeps them within
`diagnostic.rs` but changes the surrounding `impl Diagnostic` block to
`impl DiagnosticBuilder`. (I intend to move things around later, to give
a more sensible code layout.)
`Diagnostic` keeps a few methods that it still needs, like `sub`,
`arg`, and `replace_args`.
The `forward!` macro, which defined two additional methods per call
(e.g. `note` and `with_note`), is replaced by the `with_fn!` macro,
which defines one additional method per call (e.g. `with_note`). It's
now also only used when necessary -- not all modifier methods currently
need a `with_*` form. (New ones can be easily added as necessary.)
All this also requires changing `trait AddToDiagnostic` so its methods
take `DiagnosticBuilder` instead of `Diagnostic`, which leads to many
mechanical changes. `SubdiagnosticMessageOp` gains a type parameter `G`.
There are three subdiagnostics -- `DelayedAtWithoutNewline`,
`DelayedAtWithNewline`, and `InvalidFlushedDelayedDiagnosticLevel` --
that are created within the diagnostics machinery and appended to
external diagnostics. These are handled at the `Diagnostic` level, which
means it's now hard to construct them via `derive(Diagnostic)`, so
instead we construct them by hand. This has no effect on what they look
like when printed.
There are lots of new `allow` markers for `untranslatable_diagnostics`
and `diagnostics_outside_of_impl`. This is because
`#[rustc_lint_diagnostics]` annotations were present on the `Diagnostic`
modifier methods, but missing from the `DiagnosticBuilder` modifier
methods. They're now present.
2024-02-06 05:44:30 +00:00
|
|
|
self,
|
2024-02-22 23:20:45 +00:00
|
|
|
diag: &mut Diag<'_, G>,
|
2024-04-18 19:18:35 +00:00
|
|
|
_: &F,
|
Reduce capabilities of `Diagnostic`.
Currently many diagnostic modifier methods are available on both
`Diagnostic` and `DiagnosticBuilder`. This commit removes most of them
from `Diagnostic`. To minimize the diff size, it keeps them within
`diagnostic.rs` but changes the surrounding `impl Diagnostic` block to
`impl DiagnosticBuilder`. (I intend to move things around later, to give
a more sensible code layout.)
`Diagnostic` keeps a few methods that it still needs, like `sub`,
`arg`, and `replace_args`.
The `forward!` macro, which defined two additional methods per call
(e.g. `note` and `with_note`), is replaced by the `with_fn!` macro,
which defines one additional method per call (e.g. `with_note`). It's
now also only used when necessary -- not all modifier methods currently
need a `with_*` form. (New ones can be easily added as necessary.)
All this also requires changing `trait AddToDiagnostic` so its methods
take `DiagnosticBuilder` instead of `Diagnostic`, which leads to many
mechanical changes. `SubdiagnosticMessageOp` gains a type parameter `G`.
There are three subdiagnostics -- `DelayedAtWithoutNewline`,
`DelayedAtWithNewline`, and `InvalidFlushedDelayedDiagnosticLevel` --
that are created within the diagnostics machinery and appended to
external diagnostics. These are handled at the `Diagnostic` level, which
means it's now hard to construct them via `derive(Diagnostic)`, so
instead we construct them by hand. This has no effect on what they look
like when printed.
There are lots of new `allow` markers for `untranslatable_diagnostics`
and `diagnostics_outside_of_impl`. This is because
`#[rustc_lint_diagnostics]` annotations were present on the `Diagnostic`
modifier methods, but missing from the `DiagnosticBuilder` modifier
methods. They're now present.
2024-02-06 05:44:30 +00:00
|
|
|
) {
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-14 21:24:10 +00:00
|
|
|
#[derive(LintDiagnostic)]
|
|
|
|
#[diag(pattern_analysis_excluside_range_missing_max)]
|
2024-07-28 05:12:14 +00:00
|
|
|
pub struct ExclusiveRangeMissingMax {
|
2024-01-14 21:24:10 +00:00
|
|
|
#[label]
|
|
|
|
#[suggestion(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,
|
2024-07-28 05:12:14 +00:00
|
|
|
pub max: String, // a printed pattern
|
2024-01-14 21:24:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(LintDiagnostic)]
|
|
|
|
#[diag(pattern_analysis_excluside_range_missing_gap)]
|
2024-07-28 05:12:14 +00:00
|
|
|
pub struct ExclusiveRangeMissingGap {
|
2024-01-14 21:24:10 +00:00
|
|
|
#[label]
|
|
|
|
#[suggestion(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,
|
2024-07-28 05:12:14 +00:00
|
|
|
pub gap: String, // a printed pattern
|
2024-01-14 21:24:10 +00:00
|
|
|
/// Suggest `lo..=gap` instead.
|
|
|
|
pub suggestion: String,
|
|
|
|
#[subdiagnostic]
|
|
|
|
/// All these ranges skipped over `gap` which we think is probably a mistake.
|
2024-07-28 05:12:14 +00:00
|
|
|
pub gap_with: Vec<GappedRange>,
|
2024-01-14 21:24:10 +00:00
|
|
|
}
|
|
|
|
|
2024-07-28 05:12:14 +00:00
|
|
|
pub struct GappedRange {
|
2024-01-14 21:24:10 +00:00
|
|
|
pub span: Span,
|
2024-07-28 05:12:14 +00:00
|
|
|
pub gap: String, // a printed pattern
|
|
|
|
pub first_range: String, // a printed pattern
|
2024-01-14 21:24:10 +00:00
|
|
|
}
|
|
|
|
|
2024-07-28 05:12:14 +00:00
|
|
|
impl Subdiagnostic for GappedRange {
|
2024-03-06 03:00:16 +00:00
|
|
|
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
2024-01-14 21:24:10 +00:00
|
|
|
self,
|
|
|
|
diag: &mut Diag<'_, G>,
|
2024-04-18 19:18:35 +00:00
|
|
|
_: &F,
|
2024-01-14 21:24:10 +00:00
|
|
|
) {
|
|
|
|
let GappedRange { span, gap, first_range } = self;
|
|
|
|
|
|
|
|
// FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]`
|
|
|
|
// does not support `#[subdiagnostic(eager)]`...
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-10 19:42:30 +00:00
|
|
|
#[derive(LintDiagnostic)]
|
|
|
|
#[diag(pattern_analysis_non_exhaustive_omitted_pattern)]
|
|
|
|
#[help]
|
|
|
|
#[note]
|
|
|
|
pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
|
|
|
|
pub scrut_ty: Ty<'tcx>,
|
|
|
|
#[subdiagnostic]
|
2024-07-28 05:12:14 +00:00
|
|
|
pub uncovered: Uncovered,
|
2023-12-10 19:42:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[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,
|
|
|
|
}
|