@@ -612,7 +612,7 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
612
612
/// regardless of the signedness.
613
613
/// For example, the pattern `-128...127i8` is encoded as `0..=255`.
614
614
/// This makes comparisons and arithmetic on interval endpoints much more
615
- /// straightforward. See `encode` and `decode ` for details.
615
+ /// straightforward. See `signed_bias ` for details.
616
616
struct IntRange < ' tcx > {
617
617
pub range : RangeInclusive < u128 > ,
618
618
pub ty : Ty < ' tcx > ,
@@ -660,6 +660,8 @@ impl<'tcx> IntRange<'tcx> {
660
660
}
661
661
}
662
662
663
+ // The return value of `signed_bias` should be
664
+ // XORed with an endpoint to encode/decode it.
663
665
fn signed_bias ( tcx : TyCtxt < ' _ , ' tcx , ' tcx > , ty : Ty < ' tcx > ) -> u128 {
664
666
match ty. sty {
665
667
ty:: TyInt ( ity) => {
@@ -670,54 +672,52 @@ impl<'tcx> IntRange<'tcx> {
670
672
}
671
673
}
672
674
673
- fn into_inner ( self ) -> ( u128 , u128 ) {
674
- self . range . into_inner ( )
675
- }
676
- }
677
-
678
- /// Given a pattern in a `match` and a collection of ranges corresponding to the
679
- /// domain of values of a type (say, an integer), return a new collection of ranges
680
- /// corresponding to those ranges minus the ranges covered by the pattern.
681
- fn ranges_subtract_pattern < ' a , ' tcx > ( cx : & mut MatchCheckCtxt < ' a , ' tcx > ,
682
- pat_ctor : & Constructor < ' tcx > ,
683
- ranges : Vec < Constructor < ' tcx > > )
684
- -> Vec < Constructor < ' tcx > > {
685
- if let Some ( pat_interval) = IntRange :: from_ctor ( cx. tcx , pat_ctor) {
675
+ /// Given an `IntRange` corresponding to a pattern in a `match` and a collection of
676
+ /// ranges corresponding to the domain of values of a type (say, an integer), return
677
+ /// a new collection of ranges corresponding to the original ranges minus the ranges
678
+ /// covered by the `IntRange`.
679
+ fn subtract_from ( self ,
680
+ tcx : TyCtxt < ' _ , ' tcx , ' tcx > ,
681
+ ranges : Vec < Constructor < ' tcx > > )
682
+ -> Vec < Constructor < ' tcx > > {
683
+ let ranges = ranges. into_iter ( ) . filter_map ( |r| {
684
+ IntRange :: from_ctor ( tcx, & r) . map ( |i| i. range )
685
+ } ) ;
686
+ // Convert a `RangeInclusive` to a `ConstantValue` or inclusive `ConstantRange`.
687
+ let bias = IntRange :: signed_bias ( tcx, self . ty ) ;
688
+ let ty = ty:: ParamEnv :: empty ( ) . and ( self . ty ) ;
689
+ let range_to_constant = |r : RangeInclusive < u128 > | {
690
+ let ( lo, hi) = r. into_inner ( ) ;
691
+ if lo == hi {
692
+ ConstantValue ( ty:: Const :: from_bits ( tcx, lo ^ bias, ty) )
693
+ } else {
694
+ ConstantRange ( ty:: Const :: from_bits ( tcx, lo ^ bias, ty) ,
695
+ ty:: Const :: from_bits ( tcx, hi ^ bias, ty) ,
696
+ RangeEnd :: Included )
697
+ }
698
+ } ;
686
699
let mut remaining_ranges = vec ! [ ] ;
687
- let mut ranges: Vec < _ > = ranges. into_iter ( ) . filter_map ( |r| {
688
- IntRange :: from_ctor ( cx. tcx , & r) . map ( |i| i. into_inner ( ) )
689
- } ) . collect ( ) ;
690
- let ty = pat_interval. ty ;
691
- let ( pat_interval_lo, pat_interval_hi) = pat_interval. into_inner ( ) ;
692
- for ( subrange_lo, subrange_hi) in ranges {
693
- if pat_interval_lo > subrange_hi || subrange_lo > pat_interval_hi {
700
+ let ( lo, hi) = self . range . into_inner ( ) ;
701
+ for subrange in ranges {
702
+ let ( subrange_lo, subrange_hi) = subrange. into_inner ( ) ;
703
+ if lo > subrange_hi || subrange_lo > hi {
694
704
// The pattern doesn't intersect with the subrange at all,
695
705
// so the subrange remains untouched.
696
- remaining_ranges. push ( subrange_lo..=subrange_hi) ;
706
+ remaining_ranges. push ( range_to_constant ( subrange_lo..=subrange_hi) ) ;
697
707
} else {
698
- if pat_interval_lo > subrange_lo {
708
+ if lo > subrange_lo {
699
709
// The pattern intersects an upper section of the
700
710
// subrange, so a lower section will remain.
701
- remaining_ranges. push ( subrange_lo..=( pat_interval_lo - 1 ) ) ;
711
+ remaining_ranges. push ( range_to_constant ( subrange_lo..=( lo - 1 ) ) ) ;
702
712
}
703
- if pat_interval_hi < subrange_hi {
713
+ if hi < subrange_hi {
704
714
// The pattern intersects a lower section of the
705
715
// subrange, so an upper section will remain.
706
- remaining_ranges. push ( ( pat_interval_hi + 1 ) ..=subrange_hi) ;
716
+ remaining_ranges. push ( range_to_constant ( ( hi + 1 ) ..=subrange_hi) ) ;
707
717
}
708
718
}
709
719
}
710
- // Convert the remaining ranges from pairs to inclusive `ConstantRange`s.
711
- remaining_ranges. into_iter ( ) . map ( |r| {
712
- let ( lo, hi) = r. into_inner ( ) ;
713
- let bias = IntRange :: signed_bias ( cx. tcx , ty) ;
714
- let ty = ty:: ParamEnv :: empty ( ) . and ( ty) ;
715
- ConstantRange ( ty:: Const :: from_bits ( cx. tcx , lo ^ bias, ty) ,
716
- ty:: Const :: from_bits ( cx. tcx , hi ^ bias, ty) ,
717
- RangeEnd :: Included )
718
- } ) . collect ( )
719
- } else {
720
- ranges
720
+ remaining_ranges
721
721
}
722
722
}
723
723
@@ -818,38 +818,41 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
818
818
// `missing_ctors` are those that should have appeared
819
819
// as patterns in the `match` expression, but did not.
820
820
let mut missing_ctors = vec ! [ ] ;
821
- ' req: for req_ctor in & all_ctors {
822
- let mut sub_ctors = vec ! [ req_ctor. clone( ) ] ;
821
+ for req_ctor in & all_ctors {
823
822
// The only constructor patterns for which it is valid to
824
823
// treat the values as constructors are ranges (see
825
824
// `all_constructors` for details).
826
825
let consider_value_constructors = value_constructors && match req_ctor {
827
826
ConstantRange ( ..) => true ,
828
827
_ => false ,
829
828
} ;
830
- for used_ctor in & used_ctors {
831
- if consider_value_constructors {
832
- sub_ctors = ranges_subtract_pattern ( cx, used_ctor, sub_ctors) ;
829
+ if consider_value_constructors {
830
+ let mut refined_ctors = vec ! [ req_ctor. clone( ) ] ;
831
+ for used_ctor in & used_ctors {
832
+ // Refine the required constructors for the type by subtracting
833
+ // the range defined by the current constructor pattern.
834
+ refined_ctors = match IntRange :: from_ctor ( cx. tcx , used_ctor) {
835
+ Some ( interval) => interval. subtract_from ( cx. tcx , refined_ctors) ,
836
+ None => refined_ctors,
837
+ } ;
833
838
// If the constructor patterns that have been considered so far
834
839
// already cover the entire range of values, then we the
835
840
// constructor is not missing, and we can move on to the next one.
836
- if sub_ctors. is_empty ( ) {
837
- continue ' req;
838
- }
839
- } else {
840
- // If the pattern for the required constructor
841
- // appears in the `match`, then it is not missing,
842
- // and we can move on to the next one.
843
- if used_ctor == req_ctor {
844
- continue ' req;
841
+ if refined_ctors. is_empty ( ) {
842
+ break ;
845
843
}
846
844
}
845
+ // If a constructor has not been matched, then it is missing.
846
+ // We add `refined_ctors` instead of `req_ctor`, because then we can
847
+ // provide more detailed error information about precisely which
848
+ // ranges have been omitted.
849
+ missing_ctors. extend ( refined_ctors) ;
850
+ } else {
851
+ // A constructor is missing if it never appears in a `match` arm.
852
+ if !used_ctors. iter ( ) . any ( |used_ctor| used_ctor == req_ctor) {
853
+ missing_ctors. push ( req_ctor. clone ( ) ) ;
854
+ }
847
855
}
848
- // If a constructor has not been matched, then it is missing.
849
- // We add `sub_ctors` instead of `req_ctor`, because then we can
850
- // provide more detailed error information about precisely which
851
- // ranges have been omitted.
852
- missing_ctors. extend ( sub_ctors) ;
853
856
}
854
857
855
858
// `missing_ctors` is the set of constructors from the same type as the
@@ -968,11 +971,11 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
968
971
match ctor {
969
972
// A constant range of length 1 is simply
970
973
// a constant value.
971
- ConstantRange ( lo , hi , _ ) if lo == hi => {
974
+ ConstantValue ( value ) => {
972
975
Witness ( vec ! [ Pattern {
973
976
ty: pcx. ty,
974
977
span: DUMMY_SP ,
975
- kind: box PatternKind :: Constant { value: lo } ,
978
+ kind: box PatternKind :: Constant { value } ,
976
979
} ] )
977
980
}
978
981
// We always report missing intervals
0 commit comments