Skip to content

Commit

Permalink
Rollup merge of rust-lang#56695 - varkor:let-exhaustive-range, r=este…
Browse files Browse the repository at this point in the history
…bank

Fix irrefutable matches on integer ranges

Fixes rust-lang#56659.
  • Loading branch information
kennytm authored Dec 14, 2018
2 parents 35fe8c9 + 510a9ff commit 53a2de2
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 1 deletion.
34 changes: 33 additions & 1 deletion src/librustc_mir/build/matches/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ use build::{BlockAnd, BlockAndExtension, Builder};
use build::matches::{Ascription, Binding, MatchPair, Candidate};
use hair::*;
use rustc::mir::*;
use rustc::ty;
use rustc::ty::layout::{Integer, IntegerExt, Size};
use syntax::attr::{SignedInt, UnsignedInt};
use rustc::hir::RangeEnd;

use std::mem;

Expand Down Expand Up @@ -62,6 +66,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
match_pair: MatchPair<'pat, 'tcx>,
candidate: &mut Candidate<'pat, 'tcx>)
-> Result<(), MatchPair<'pat, 'tcx>> {
let tcx = self.hir.tcx();
match *match_pair.pattern.kind {
PatternKind::AscribeUserType { ref subpattern, ref user_ty, user_ty_span } => {
candidate.ascriptions.push(Ascription {
Expand Down Expand Up @@ -104,7 +109,34 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
Err(match_pair)
}

PatternKind::Range { .. } => {
PatternKind::Range { lo, hi, ty, end } => {
let range = match ty.sty {
ty::Char => {
Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32)))
}
ty::Int(ity) => {
// FIXME(49937): refactor these bit manipulations into interpret.
let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
let min = 1u128 << (size.bits() - 1);
let max = (1u128 << (size.bits() - 1)) - 1;
Some((min, max, size))
}
ty::Uint(uty) => {
// FIXME(49937): refactor these bit manipulations into interpret.
let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size();
let max = !0u128 >> (128 - size.bits());
Some((0, max, size))
}
_ => None,
};
if let Some((min, max, sz)) = range {
if let (Some(lo), Some(hi)) = (lo.val.try_to_bits(sz), hi.val.try_to_bits(sz)) {
if lo <= min && (hi > max || hi == max && end == RangeEnd::Included) {
// Irrefutable pattern match.
return Ok(());
}
}
}
Err(match_pair)
}

Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// run-pass

fn main() {
let -2147483648..=2147483647 = 1;
let 0..=255 = 0u8;
let -128..=127 = 0i8;
let '\u{0000}'..='\u{10FFFF}' = 'v';
}

0 comments on commit 53a2de2

Please sign in to comment.