diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 87d5795484e3..4f4d814dee96 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -641,6 +641,15 @@ impl<'tcx> Constructor<'tcx> { IntRange::should_treat_range_exhaustively(tcx, ty) } + fn is_integral_range(&self) -> bool { + let ty = match self { + ConstantValue(value, _) => value.ty, + ConstantRange(_, _, ty, _, _) => ty, + _ => return false, + }; + IntRange::is_integral(ty) + } + fn variant_index_for_adt<'a>( &self, cx: &MatchCheckCtxt<'a, 'tcx>, @@ -1471,6 +1480,12 @@ impl<'tcx> IntRange<'tcx> { } } + fn is_subrange(&self, other: &Self) -> bool { + let (lo, hi) = (*self.range.start(), *self.range.end()); + let (other_lo, other_hi) = (*other.range.start(), *other.range.end()); + other_lo <= lo && hi <= other_hi + } + fn suspicious_intersection(&self, other: &Self) -> bool { // `false` in the following cases: // 1 ---- // 1 ---------- // 1 ---- // 1 ---- @@ -2300,6 +2315,8 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>( IntRange::from_pat(cx.tcx, cx.param_env, pat), ) { (Some(ctor), Some(pat)) => ctor.intersection(&pat).map(|_| { + // Constructor splitting should ensure that all intersections we encounter + // are actually inclusions. let (pat_lo, pat_hi) = pat.range.into_inner(); let (ctor_lo, ctor_hi) = ctor.range.into_inner(); assert!(pat_lo <= ctor_lo && ctor_hi <= pat_hi); @@ -2307,6 +2324,16 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>( }), _ => None, } + } else if constructor.is_integral_range() { + // If we have an integer range that should not be matched exhaustively, fallback to + // checking for inclusion. + match ( + IntRange::from_ctor(cx.tcx, cx.param_env, constructor), + IntRange::from_pat(cx.tcx, cx.param_env, pat), + ) { + (Some(ctor), Some(pat)) if ctor.is_subrange(&pat) => Some(PatStack::default()), + _ => None, + } } else { // Fallback for non-ranges and ranges that involve // floating-point numbers, which are not conveniently handled