Skip to content

Commit e3357d9

Browse files
committed
Implement interval checking
1 parent b559042 commit e3357d9

File tree

1 file changed

+164
-10
lines changed

1 file changed

+164
-10
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 164 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ impl<'tcx> Constructor<'tcx> {
273273
}
274274
}
275275

276-
#[derive(Clone)]
276+
#[derive(Clone, Debug)]
277277
pub enum Usefulness<'tcx> {
278278
Useful,
279279
UsefulWithWitness(Vec<Witness<'tcx>>),
@@ -425,10 +425,10 @@ impl<'tcx> Witness<'tcx> {
425425
/// Option<!> we do not include Some(_) in the returned list of constructors.
426426
fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
427427
pcx: PatternContext<'tcx>)
428-
-> Vec<Constructor<'tcx>>
428+
-> (Vec<Constructor<'tcx>>, bool)
429429
{
430430
debug!("all_constructors({:?})", pcx.ty);
431-
match pcx.ty.sty {
431+
(match pcx.ty.sty {
432432
ty::TyBool => {
433433
[true, false].iter().map(|&b| {
434434
ConstantValue(ty::Const::from_bool(cx.tcx, b))
@@ -457,14 +457,21 @@ 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) => {
461+
return (vec![
462+
ConstantRange(ty::Const::from_usize(cx.tcx, 0),
463+
ty::Const::from_usize(cx.tcx, 100),
464+
RangeEnd::Excluded),
465+
], true)
466+
}
460467
_ => {
461468
if cx.is_uninhabited(pcx.ty) {
462469
vec![]
463470
} else {
464471
vec![Single]
465472
}
466473
}
467-
}
474+
}, false)
468475
}
469476

470477
fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
@@ -656,11 +663,148 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
656663
pat_constructors(cx, row[0], pcx).unwrap_or(vec![])
657664
}).collect();
658665
debug!("used_ctors = {:#?}", used_ctors);
659-
let all_ctors = all_constructors(cx, pcx);
666+
let (all_ctors, _ranged) = all_constructors(cx, pcx);
660667
debug!("all_ctors = {:#?}", all_ctors);
661-
let missing_ctors: Vec<Constructor> = all_ctors.iter().filter(|c| {
662-
!used_ctors.contains(*c)
663-
}).cloned().collect();
668+
669+
fn to_inc_range_pair<'tcx>(tcx: TyCtxt<'_, '_, '_>, ctor: &Constructor<'tcx>) -> Option<(u64, u64)> {
670+
match ctor {
671+
Single | Variant(_) | Slice(_) => {
672+
None
673+
}
674+
ConstantValue(const_) => {
675+
if let Some(val) = const_.assert_usize(tcx) {
676+
return Some((val, val));
677+
}
678+
None
679+
}
680+
ConstantRange(lo, hi, end) => {
681+
if let Some(lo) = lo.assert_usize(tcx) {
682+
if let Some(hi) = hi.assert_usize(tcx) {
683+
if lo > hi || lo == hi && end == &RangeEnd::Excluded {
684+
return None;
685+
} else if end == &RangeEnd::Included {
686+
return Some((lo, hi));
687+
} else {
688+
return Some((lo, hi - 1));
689+
}
690+
}
691+
}
692+
None
693+
}
694+
}
695+
}
696+
697+
fn intersect<'a, 'tcx>(
698+
_deb: bool,
699+
cx: &mut MatchCheckCtxt<'a, 'tcx>,
700+
ranges: Vec<Constructor<'tcx>>,
701+
ctor: &Constructor<'tcx>)
702+
-> (Vec<Constructor<'tcx>>, bool) {
703+
if let Some((lo1, hi1)) = to_inc_range_pair(cx.tcx, ctor) {
704+
let mut ctor_was_useful = false;
705+
// values only consists of ranges
706+
let mut new_ranges = vec![];
707+
let mut ranges: Vec<_> =
708+
ranges.into_iter().filter_map(|r| to_inc_range_pair(cx.tcx, &r)).collect();
709+
while let Some((lo2, hi2)) = ranges.pop() {
710+
eprintln!("{:?} {:?}", (lo2, hi2), (lo1, hi1));
711+
if lo1 <= lo2 && hi1 >= hi2 {
712+
if _deb { eprintln!("case 1"); }
713+
ctor_was_useful = true;
714+
continue;
715+
}
716+
if lo1 > hi2 || hi1 < lo2 {
717+
if _deb { eprintln!("case 2"); }
718+
new_ranges.push((lo2, hi2));
719+
continue;
720+
}
721+
if lo1 <= lo2 {
722+
if _deb { eprintln!("case 3"); }
723+
ctor_was_useful = true;
724+
if (hi1 + 1, hi2) == (lo2, hi2) {
725+
new_ranges.push((hi1 + 1, hi2));
726+
} else {
727+
ranges.push((hi1 + 1, hi2));
728+
}
729+
continue;
730+
}
731+
if hi1 >= hi2 {
732+
if _deb { eprintln!("case 4"); }
733+
ctor_was_useful = true;
734+
if (lo2, lo1 - 1) == (lo2, hi2) {
735+
new_ranges.push((lo2, lo1 - 1));
736+
} else {
737+
ranges.push((lo2, lo1 - 1));
738+
}
739+
continue;
740+
}
741+
ctor_was_useful = true;
742+
ranges.push((lo2, lo1));
743+
ranges.push((hi1, hi2));
744+
if _deb { eprintln!("case 5"); }
745+
}
746+
// transform ranges to proper format
747+
(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)
751+
}).collect(), ctor_was_useful)
752+
} else {
753+
(ranges, false)
754+
}
755+
}
756+
757+
// `used_ctors` are all the constructors that appear in patterns (must check if guards)
758+
// `all_ctors` are all the necessary constructors
759+
let mut missing_ctors = vec![];
760+
let mut all_actual_ctors = vec![];
761+
'req: for req_ctor in all_ctors.clone() {
762+
if _deb {
763+
eprintln!("req_ctor before {:?}", req_ctor);
764+
}
765+
let mut cur = vec![req_ctor.clone()];
766+
for used_ctor in &used_ctors {
767+
if _deb {
768+
eprintln!("cut {:?}", used_ctor);
769+
}
770+
if cur.iter().all(|ctor| {
771+
match ctor {
772+
ConstantRange(..) => true,
773+
_ => false,
774+
}
775+
}) {
776+
let (cur2, ctor_was_useful) = intersect(_deb, cx, cur, used_ctor);
777+
cur = cur2;
778+
if ctor_was_useful {
779+
all_actual_ctors.push(used_ctor.clone());
780+
}
781+
if cur.is_empty() {
782+
continue 'req;
783+
}
784+
} else {
785+
if used_ctor == &req_ctor {
786+
continue 'req;
787+
}
788+
}
789+
}
790+
if _deb {
791+
eprintln!("req_ctor after {:?}", cur);
792+
}
793+
missing_ctors.extend(cur);
794+
}
795+
796+
// let missing_ctors: Vec<Constructor> = all_ctors.iter().filter(|c| {
797+
// !used_ctors.contains(*c)
798+
// }).cloned().collect();
799+
800+
if _deb {
801+
eprintln!("used_ctors {:?}", used_ctors);
802+
eprintln!("missing_ctors {:?}", missing_ctors);
803+
}
804+
805+
// if !all_actual_ctors.is_empty() {
806+
// all_ctors = all_actual_ctors;
807+
// }
664808

665809
// `missing_ctors` is the set of constructors from the same type as the
666810
// first column of `matrix` that are matched only by wildcard patterns
@@ -693,10 +837,16 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
693837
let is_non_exhaustive = is_privately_empty || is_declared_nonexhaustive;
694838

695839
if missing_ctors.is_empty() && !is_non_exhaustive {
696-
all_ctors.into_iter().map(|c| {
840+
if _ranged && _deb {
841+
return NotUseful;
842+
}
843+
let z = all_ctors.into_iter().map(|c| {
697844
is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
698-
}).find(|result| result.is_useful()).unwrap_or(NotUseful)
845+
}).find(|result| result.is_useful()).unwrap_or(NotUseful);
846+
if _deb { eprintln!("ABC 1 {:?}", z); }
847+
z
699848
} else {
849+
if _deb { eprintln!("ABC 2"); }
700850
let matrix = rows.iter().filter_map(|r| {
701851
if r[0].is_wildcard() {
702852
Some(r[1..].to_vec())
@@ -706,6 +856,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
706856
}).collect();
707857
match is_useful(cx, &matrix, &v[1..], witness) {
708858
UsefulWithWitness(pats) => {
859+
if _deb { eprintln!("ABC 3"); }
709860
let cx = &*cx;
710861
// In this case, there's at least one "free"
711862
// constructor that is only matched against by
@@ -752,6 +903,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
752903
// satisfied with `(_, _, true)`. In this case,
753904
// `used_ctors` is empty.
754905
let new_witnesses = if is_non_exhaustive || used_ctors.is_empty() {
906+
if _deb { eprintln!("ABC 4"); }
755907
// All constructors are unused. Add wild patterns
756908
// rather than each individual constructor
757909
pats.into_iter().map(|mut witness| {
@@ -763,6 +915,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
763915
witness
764916
}).collect()
765917
} else {
918+
if _deb { eprintln!("ABC 5"); }
766919
pats.into_iter().flat_map(|witness| {
767920
missing_ctors.iter().map(move |ctor| {
768921
witness.clone().push_wild_constructor(cx, ctor, pcx.ty)
@@ -1062,6 +1215,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
10621215
PatternKind::Leaf { ref subpatterns } => {
10631216
Some(patterns_for_variant(subpatterns, wild_patterns))
10641217
}
1218+
10651219
PatternKind::Deref { ref subpattern } => {
10661220
Some(vec![subpattern])
10671221
}

0 commit comments

Comments
 (0)