Migrate deconstruct_pat.rs

This commit is contained in:
mejrs 2022-12-20 16:43:34 +01:00 committed by David Tolnay
parent 519b1abd19
commit 5d2b9a9ed0
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
5 changed files with 48 additions and 23 deletions

View File

@ -318,3 +318,9 @@ mir_build_indirect_structural_match =
mir_build_nontrivial_structural_match = mir_build_nontrivial_structural_match =
to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]` to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
mir_build_overlapping_range_endpoints = multiple patterns overlap on their endpoints
.range = ... with this range
.note = you likely meant to write mutually exclusive ranges
mir_build_overlapping_range = this range overlaps on `{$range}`...

View File

@ -9,6 +9,7 @@
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::RangeEnd; use rustc_hir::RangeEnd;
@ -575,6 +576,12 @@ impl<'tcx> Pat<'tcx> {
} }
} }
impl<'tcx> IntoDiagnosticArg for Pat<'tcx> {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
format!("{}", self).into_diagnostic_arg()
}
}
#[derive(Clone, Debug, HashStable)] #[derive(Clone, Debug, HashStable)]
pub struct Ascription<'tcx> { pub struct Ascription<'tcx> {
pub annotation: CanonicalUserTypeAnnotation<'tcx>, pub annotation: CanonicalUserTypeAnnotation<'tcx>,

View File

@ -4,6 +4,7 @@ use rustc_errors::{
error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan, error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan,
}; };
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::thir::Pat;
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_span::{symbol::Ident, Span}; use rustc_span::{symbol::Ident, Span};
@ -665,3 +666,22 @@ pub struct IndirectStructuralMatch<'tcx> {
pub struct NontrivialStructuralMatch<'tcx> { pub struct NontrivialStructuralMatch<'tcx> {
pub non_sm_ty: Ty<'tcx>, pub non_sm_ty: Ty<'tcx>,
} }
#[derive(LintDiagnostic)]
#[diag(mir_build_overlapping_range_endpoints)]
#[note]
pub struct OverlappingRangeEndpoints<'tcx> {
#[label(range)]
pub range: Span,
#[subdiagnostic]
pub overlap: Overlap<'tcx>,
}
#[derive(Debug)]
#[derive(Subdiagnostic)]
#[label(mir_build_overlapping_range)]
pub struct Overlap<'tcx> {
#[primary_span]
pub span: Span,
pub range: Pat<'tcx>,
}

View File

@ -67,6 +67,7 @@ use self::SliceKind::*;
use super::compare_const_vals; use super::compare_const_vals;
use super::usefulness::{MatchCheckCtxt, PatCtxt}; use super::usefulness::{MatchCheckCtxt, PatCtxt};
use crate::errors::{Overlap, OverlappingRangeEndpoints};
/// Recursively expand this pattern into its subpatterns. Only useful for or-patterns. /// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> { fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> {
@ -96,7 +97,7 @@ fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> {
/// `IntRange` is never used to encode an empty range or a "range" that wraps /// `IntRange` is never used to encode an empty range or a "range" that wraps
/// around the (offset) space: i.e., `range.lo <= range.hi`. /// around the (offset) space: i.e., `range.lo <= range.hi`.
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub(super) struct IntRange { pub(crate) struct IntRange {
range: RangeInclusive<u128>, range: RangeInclusive<u128>,
/// Keeps the bias used for encoding the range. It depends on the type of the range and /// Keeps the bias used for encoding the range. It depends on the type of the range and
/// possibly the pointer size of the current architecture. The algorithm ensures we never /// possibly the pointer size of the current architecture. The algorithm ensures we never
@ -284,32 +285,24 @@ impl IntRange {
return; return;
} }
let overlaps: Vec<_> = pats // Get the first overlap. We get only the first rather than all of them
// because displaying multiple overlaps requires a way to eagerly translate
// lintdiagnostics, but that doesn't exist.
let overlap = pats
.filter_map(|pat| Some((pat.ctor().as_int_range()?, pat.span()))) .filter_map(|pat| Some((pat.ctor().as_int_range()?, pat.span())))
.filter(|(range, _)| self.suspicious_intersection(range)) .filter(|(range, _)| self.suspicious_intersection(range))
.map(|(range, span)| (self.intersection(&range).unwrap(), span)) .map(|(range, span)| Overlap {
.collect(); range: self.intersection(&range).unwrap().to_pat(pcx.cx.tcx, pcx.ty),
span,
})
.next();
if !overlaps.is_empty() { if let Some(overlap) = overlap {
pcx.cx.tcx.struct_span_lint_hir( pcx.cx.tcx.emit_spanned_lint(
lint::builtin::OVERLAPPING_RANGE_ENDPOINTS, lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
hir_id, hir_id,
pcx.span, pcx.span,
"multiple patterns overlap on their endpoints", OverlappingRangeEndpoints { overlap, range: pcx.span },
|lint| {
for (int_range, span) in overlaps {
lint.span_label(
span,
&format!(
"this range overlaps on `{}`...",
int_range.to_pat(pcx.cx.tcx, pcx.ty)
),
);
}
lint.span_label(pcx.span, "... with this range");
lint.note("you likely meant to write mutually exclusive ranges");
lint
},
); );
} }
} }

View File

@ -59,7 +59,6 @@ error: multiple patterns overlap on their endpoints
LL | 0..=10 => {} LL | 0..=10 => {}
| ------ this range overlaps on `10_u8`... | ------ this range overlaps on `10_u8`...
LL | 20..=30 => {} LL | 20..=30 => {}
| ------- this range overlaps on `20_u8`...
LL | 10..=20 => {} LL | 10..=20 => {}
| ^^^^^^^ ... with this range | ^^^^^^^ ... with this range
| |