@@ -273,7 +273,7 @@ impl<'tcx> Constructor<'tcx> {
273
273
}
274
274
}
275
275
276
- #[ derive( Clone ) ]
276
+ #[ derive( Clone , Debug ) ]
277
277
pub enum Usefulness < ' tcx > {
278
278
Useful ,
279
279
UsefulWithWitness ( Vec < Witness < ' tcx > > ) ,
@@ -425,10 +425,10 @@ impl<'tcx> Witness<'tcx> {
425
425
/// Option<!> we do not include Some(_) in the returned list of constructors.
426
426
fn all_constructors < ' a , ' tcx : ' a > ( cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
427
427
pcx : PatternContext < ' tcx > )
428
- -> Vec < Constructor < ' tcx > >
428
+ -> ( Vec < Constructor < ' tcx > > , bool )
429
429
{
430
430
debug ! ( "all_constructors({:?})" , pcx. ty) ;
431
- match pcx. ty . sty {
431
+ ( match pcx. ty . sty {
432
432
ty:: TyBool => {
433
433
[ true , false ] . iter ( ) . map ( |& b| {
434
434
ConstantValue ( ty:: Const :: from_bool ( cx. tcx , b) )
@@ -457,14 +457,21 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
457
457
. map ( |v| Variant ( v. did ) )
458
458
. collect ( )
459
459
}
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
+ }
460
467
_ => {
461
468
if cx. is_uninhabited ( pcx. ty ) {
462
469
vec ! [ ]
463
470
} else {
464
471
vec ! [ Single ]
465
472
}
466
473
}
467
- }
474
+ } , false )
468
475
}
469
476
470
477
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>,
656
663
pat_constructors ( cx, row[ 0 ] , pcx) . unwrap_or ( vec ! [ ] )
657
664
} ) . collect ( ) ;
658
665
debug ! ( "used_ctors = {:#?}" , used_ctors) ;
659
- let all_ctors = all_constructors ( cx, pcx) ;
666
+ let ( all_ctors, _ranged ) = all_constructors ( cx, pcx) ;
660
667
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
+ // }
664
808
665
809
// `missing_ctors` is the set of constructors from the same type as the
666
810
// 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>,
693
837
let is_non_exhaustive = is_privately_empty || is_declared_nonexhaustive;
694
838
695
839
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| {
697
844
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
699
848
} else {
849
+ if _deb { eprintln ! ( "ABC 2" ) ; }
700
850
let matrix = rows. iter ( ) . filter_map ( |r| {
701
851
if r[ 0 ] . is_wildcard ( ) {
702
852
Some ( r[ 1 ..] . to_vec ( ) )
@@ -706,6 +856,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
706
856
} ) . collect ( ) ;
707
857
match is_useful ( cx, & matrix, & v[ 1 ..] , witness) {
708
858
UsefulWithWitness ( pats) => {
859
+ if _deb { eprintln ! ( "ABC 3" ) ; }
709
860
let cx = & * cx;
710
861
// In this case, there's at least one "free"
711
862
// 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>,
752
903
// satisfied with `(_, _, true)`. In this case,
753
904
// `used_ctors` is empty.
754
905
let new_witnesses = if is_non_exhaustive || used_ctors. is_empty ( ) {
906
+ if _deb { eprintln ! ( "ABC 4" ) ; }
755
907
// All constructors are unused. Add wild patterns
756
908
// rather than each individual constructor
757
909
pats. into_iter ( ) . map ( |mut witness| {
@@ -763,6 +915,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
763
915
witness
764
916
} ) . collect ( )
765
917
} else {
918
+ if _deb { eprintln ! ( "ABC 5" ) ; }
766
919
pats. into_iter ( ) . flat_map ( |witness| {
767
920
missing_ctors. iter ( ) . map ( move |ctor| {
768
921
witness. clone ( ) . push_wild_constructor ( cx, ctor, pcx. ty )
@@ -1062,6 +1215,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
1062
1215
PatternKind :: Leaf { ref subpatterns } => {
1063
1216
Some ( patterns_for_variant ( subpatterns, wild_patterns) )
1064
1217
}
1218
+
1065
1219
PatternKind :: Deref { ref subpattern } => {
1066
1220
Some ( vec ! [ subpattern] )
1067
1221
}
0 commit comments