Skip to content

Commit 384db4f

Browse files
committed
Add support for all integer types
1 parent b3d2baf commit 384db4f

File tree

1 file changed

+58
-16
lines changed

1 file changed

+58
-16
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -457,13 +457,52 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
457457
.map(|v| Variant(v.did))
458458
.collect()
459459
}
460-
ty::TyUint(ast::UintTy::Usize) => {
460+
ty::TyChar => {
461+
let (min, max) = (0u128, char::MAX as u128);
461462
return (vec![
462-
ConstantRange(ty::Const::from_usize(cx.tcx, 0),
463-
ty::Const::from_usize(cx.tcx, 100),
464-
RangeEnd::Excluded),
463+
ConstantRange(ty::Const::from_bits(cx.tcx, min, cx.tcx.types.char),
464+
ty::Const::from_bits(cx.tcx, max, cx.tcx.types.char),
465+
RangeEnd::Included),
465466
], true)
466467
}
468+
ty::TyInt(int_ty) => {
469+
use syntax::ast::IntTy::*;
470+
let (min, max, ty) = match int_ty {
471+
Isize => (isize::MIN as i128, isize::MAX as i128, cx.tcx.types.isize),
472+
I8 => ( i8::MIN as i128, i8::MAX as i128, cx.tcx.types.i8),
473+
I16 => ( i16::MIN as i128, i16::MAX as i128, cx.tcx.types.i16),
474+
I32 => ( i32::MIN as i128, i32::MAX as i128, cx.tcx.types.i32),
475+
I64 => ( i64::MIN as i128, i64::MAX as i128, cx.tcx.types.i64),
476+
I128 => ( i128::MIN as i128, i128::MAX as i128, cx.tcx.types.i128),
477+
};
478+
return (vec![
479+
ConstantRange(
480+
ty::Const::from_bits(cx.tcx, unsafe {
481+
transmute::<i128, u128>(min)
482+
}, ty),
483+
ty::Const::from_bits(cx.tcx, unsafe {
484+
transmute::<i128, u128>(max)
485+
}, ty),
486+
RangeEnd::Included
487+
),
488+
], true);
489+
}
490+
ty::TyUint(uint_ty) => {
491+
use syntax::ast::UintTy::*;
492+
let (min, (max, ty)) = (0u128, match uint_ty {
493+
Usize => (usize::MAX as u128, cx.tcx.types.usize),
494+
U8 => ( u8::MAX as u128, cx.tcx.types.u8),
495+
U16 => ( u16::MAX as u128, cx.tcx.types.u16),
496+
U32 => ( u32::MAX as u128, cx.tcx.types.u32),
497+
U64 => ( u64::MAX as u128, cx.tcx.types.u64),
498+
U128 => ( u128::MAX as u128, cx.tcx.types.u128),
499+
});
500+
return (vec![
501+
ConstantRange(ty::Const::from_bits(cx.tcx, min, ty),
502+
ty::Const::from_bits(cx.tcx, max, ty),
503+
RangeEnd::Included),
504+
], true);
505+
}
467506
_ => {
468507
if cx.is_uninhabited(pcx.ty) {
469508
vec![]
@@ -666,26 +705,27 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
666705
let (all_ctors, _ranged) = all_constructors(cx, pcx);
667706
debug!("all_ctors = {:#?}", all_ctors);
668707

669-
fn to_inc_range_pair<'tcx>(tcx: TyCtxt<'_, '_, '_>, ctor: &Constructor<'tcx>) -> Option<(u64, u64)> {
708+
fn to_inc_range_pair<'tcx>(_tcx: TyCtxt<'_, '_, '_>, ctor: &Constructor<'tcx>) -> Option<(u128, u128, Ty<'tcx>)> {
670709
match ctor {
671710
Single | Variant(_) | Slice(_) => {
672711
None
673712
}
674713
ConstantValue(const_) => {
675-
if let Some(val) = const_.assert_usize(tcx) {
676-
return Some((val, val));
714+
if let Some(val) = const_.assert_bits(const_.ty) {
715+
return Some((val, val, const_.ty));
677716
}
678717
None
679718
}
680719
ConstantRange(lo, hi, end) => {
681-
if let Some(lo) = lo.assert_usize(tcx) {
682-
if let Some(hi) = hi.assert_usize(tcx) {
720+
let ty = lo.ty;
721+
if let Some(lo) = lo.assert_bits(lo.ty) {
722+
if let Some(hi) = hi.assert_bits(hi.ty) {
683723
if lo > hi || lo == hi && end == &RangeEnd::Excluded {
684724
return None;
685725
} else if end == &RangeEnd::Included {
686-
return Some((lo, hi));
726+
return Some((lo, hi, ty));
687727
} else {
688-
return Some((lo, hi - 1));
728+
return Some((lo, hi - 1, ty));
689729
}
690730
}
691731
}
@@ -700,12 +740,14 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
700740
ranges: Vec<Constructor<'tcx>>,
701741
ctor: &Constructor<'tcx>)
702742
-> (Vec<Constructor<'tcx>>, bool) {
703-
if let Some((lo1, hi1)) = to_inc_range_pair(cx.tcx, ctor) {
743+
if let Some((lo1, hi1, ty)) = to_inc_range_pair(cx.tcx, ctor) {
704744
let mut ctor_was_useful = false;
705745
// values only consists of ranges
706746
let mut new_ranges = vec![];
707747
let mut ranges: Vec<_> =
708-
ranges.into_iter().filter_map(|r| to_inc_range_pair(cx.tcx, &r)).collect();
748+
ranges.into_iter().filter_map(|r| {
749+
to_inc_range_pair(cx.tcx, &r).map(|(lo, hi, _)| (lo, hi))
750+
}).collect();
709751
while let Some((lo2, hi2)) = ranges.pop() {
710752
// eprintln!("{:?} {:?}", (lo2, hi2), (lo1, hi1));
711753
if lo1 <= lo2 && hi1 >= hi2 {
@@ -745,9 +787,9 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
745787
}
746788
// transform ranges to proper format
747789
(new_ranges.into_iter().map(|(lo, hi)| {
748-
ConstantRange(ty::Const::from_usize(cx.tcx, lo),
749-
ty::Const::from_usize(cx.tcx, hi),
750-
RangeEnd::Included)
790+
ConstantRange(ty::Const::from_bits(cx.tcx, lo, ty),
791+
ty::Const::from_bits(cx.tcx, hi, ty),
792+
RangeEnd::Included)
751793
}).collect(), ctor_was_useful)
752794
} else {
753795
(ranges, false)

0 commit comments

Comments
 (0)