Skip to content

Commit 186fd38

Browse files
authored
Rollup merge of rust-lang#56695 - varkor:let-exhaustive-range, r=estebank
Fix irrefutable matches on integer ranges Fixes rust-lang#56659.
2 parents 3ee126c + 510a9ff commit 186fd38

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

src/librustc_mir/build/matches/simplify.rs

+33-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ use build::{BlockAnd, BlockAndExtension, Builder};
2626
use build::matches::{Ascription, Binding, MatchPair, Candidate};
2727
use hair::*;
2828
use rustc::mir::*;
29+
use rustc::ty;
30+
use rustc::ty::layout::{Integer, IntegerExt, Size};
31+
use syntax::attr::{SignedInt, UnsignedInt};
32+
use rustc::hir::RangeEnd;
2933

3034
use std::mem;
3135

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

107-
PatternKind::Range { .. } => {
112+
PatternKind::Range { lo, hi, ty, end } => {
113+
let range = match ty.sty {
114+
ty::Char => {
115+
Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32)))
116+
}
117+
ty::Int(ity) => {
118+
// FIXME(49937): refactor these bit manipulations into interpret.
119+
let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
120+
let min = 1u128 << (size.bits() - 1);
121+
let max = (1u128 << (size.bits() - 1)) - 1;
122+
Some((min, max, size))
123+
}
124+
ty::Uint(uty) => {
125+
// FIXME(49937): refactor these bit manipulations into interpret.
126+
let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size();
127+
let max = !0u128 >> (128 - size.bits());
128+
Some((0, max, size))
129+
}
130+
_ => None,
131+
};
132+
if let Some((min, max, sz)) = range {
133+
if let (Some(lo), Some(hi)) = (lo.val.try_to_bits(sz), hi.val.try_to_bits(sz)) {
134+
if lo <= min && (hi > max || hi == max && end == RangeEnd::Included) {
135+
// Irrefutable pattern match.
136+
return Ok(());
137+
}
138+
}
139+
}
108140
Err(match_pair)
109141
}
110142

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// run-pass
2+
3+
fn main() {
4+
let -2147483648..=2147483647 = 1;
5+
let 0..=255 = 0u8;
6+
let -128..=127 = 0i8;
7+
let '\u{0000}'..='\u{10FFFF}' = 'v';
8+
}

0 commit comments

Comments
 (0)