summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs')
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs67
1 files changed, 26 insertions, 41 deletions
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
index d60e8722c..aba5429da 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -45,7 +45,7 @@
use std::cell::Cell;
use std::cmp::{self, max, min, Ordering};
use std::fmt;
-use std::iter::{once, IntoIterator};
+use std::iter::once;
use std::ops::RangeInclusive;
use smallvec::{smallvec, SmallVec};
@@ -67,6 +67,7 @@ use self::SliceKind::*;
use super::compare_const_vals;
use super::usefulness::{MatchCheckCtxt, PatCtxt};
+use crate::errors::{Overlap, OverlappingRangeEndpoints};
/// 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>> {
@@ -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
/// around the (offset) space: i.e., `range.lo <= range.hi`.
#[derive(Clone, PartialEq, Eq)]
-pub(super) struct IntRange {
+pub(crate) struct IntRange {
range: RangeInclusive<u128>,
/// 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
@@ -140,27 +141,22 @@ impl IntRange {
) -> Option<IntRange> {
let ty = value.ty();
if let Some((target_size, bias)) = Self::integral_size_and_signed_bias(tcx, ty) {
- let val = (|| {
- match value {
- mir::ConstantKind::Val(ConstValue::Scalar(scalar), _) => {
- // For this specific pattern we can skip a lot of effort and go
- // straight to the result, after doing a bit of checking. (We
- // could remove this branch and just fall through, which
- // is more general but much slower.)
- return scalar.to_bits_or_ptr_internal(target_size).unwrap().left();
- }
- mir::ConstantKind::Ty(c) => match c.kind() {
- ty::ConstKind::Value(_) => bug!(
- "encountered ConstValue in mir::ConstantKind::Ty, whereas this is expected to be in ConstantKind::Val"
- ),
- _ => {}
- },
- _ => {}
+ let val = if let mir::ConstantKind::Val(ConstValue::Scalar(scalar), _) = value {
+ // For this specific pattern we can skip a lot of effort and go
+ // straight to the result, after doing a bit of checking. (We
+ // could remove this branch and just fall through, which
+ // is more general but much slower.)
+ scalar.to_bits_or_ptr_internal(target_size).unwrap().left()?
+ } else {
+ if let mir::ConstantKind::Ty(c) = value
+ && let ty::ConstKind::Value(_) = c.kind()
+ {
+ bug!("encountered ConstValue in mir::ConstantKind::Ty, whereas this is expected to be in ConstantKind::Val");
}
// This is a more general form of the previous case.
- value.try_eval_bits(tcx, param_env, ty)
- })()?;
+ value.try_eval_bits(tcx, param_env, ty)?
+ };
let val = val ^ bias;
Some(IntRange { range: val..=val, bias })
} else {
@@ -284,32 +280,21 @@ impl IntRange {
return;
}
- let overlaps: Vec<_> = pats
+ let overlap: Vec<_> = pats
.filter_map(|pat| Some((pat.ctor().as_int_range()?, pat.span())))
.filter(|(range, _)| self.suspicious_intersection(range))
- .map(|(range, span)| (self.intersection(&range).unwrap(), span))
+ .map(|(range, span)| Overlap {
+ range: self.intersection(&range).unwrap().to_pat(pcx.cx.tcx, pcx.ty),
+ span,
+ })
.collect();
- if !overlaps.is_empty() {
- pcx.cx.tcx.struct_span_lint_hir(
+ if !overlap.is_empty() {
+ pcx.cx.tcx.emit_spanned_lint(
lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
hir_id,
pcx.span,
- "multiple patterns overlap on their endpoints",
- |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
- },
+ OverlappingRangeEndpoints { overlap, range: pcx.span },
);
}
}
@@ -404,7 +389,7 @@ impl SplitIntRange {
}
/// Iterate over the contained ranges.
- fn iter<'a>(&'a self) -> impl Iterator<Item = IntRange> + Captures<'a> {
+ fn iter(&self) -> impl Iterator<Item = IntRange> + Captures<'_> {
use IntBorder::*;
let self_range = Self::to_borders(self.range.clone());
@@ -612,7 +597,7 @@ impl SplitVarLenSlice {
}
/// Iterate over the partition of this slice.
- fn iter<'a>(&'a self) -> impl Iterator<Item = Slice> + Captures<'a> {
+ fn iter(&self) -> impl Iterator<Item = Slice> + Captures<'_> {
let smaller_lengths = match self.array_len {
// The only admissible fixed-length slice is one of the array size. Whether `max_slice`
// is fixed-length or variable-length, it will be the only relevant slice to output