Fix irrefutable matches on integer ranges
This commit is contained in:
parent
1137d29d5e
commit
510a9fffa2
@ -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;
|
||||
|
||||
@ -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 {
|
||||
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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';
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user