@@ -834,17 +834,21 @@ impl<'tcx> PatRange<'tcx> {
834
834
//
835
835
// Also, for performance, it's important to only do the second `try_to_bits` if necessary.
836
836
let lo_is_min = match self . lo {
837
+ PatRangeBoundary :: NegInfinity => true ,
837
838
PatRangeBoundary :: Finite ( value) => {
838
839
let lo = value. try_to_bits ( size) . unwrap ( ) ^ bias;
839
840
lo <= min
840
841
}
842
+ PatRangeBoundary :: PosInfinity => false ,
841
843
} ;
842
844
if lo_is_min {
843
845
let hi_is_max = match self . hi {
846
+ PatRangeBoundary :: NegInfinity => false ,
844
847
PatRangeBoundary :: Finite ( value) => {
845
848
let hi = value. try_to_bits ( size) . unwrap ( ) ^ bias;
846
849
hi > max || hi == max && self . end == RangeEnd :: Included
847
850
}
851
+ PatRangeBoundary :: PosInfinity => true ,
848
852
} ;
849
853
if hi_is_max {
850
854
return Some ( true ) ;
@@ -903,11 +907,13 @@ impl<'tcx> PatRange<'tcx> {
903
907
904
908
impl < ' tcx > fmt:: Display for PatRange < ' tcx > {
905
909
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
906
- let PatRangeBoundary :: Finite ( value) = & self . lo ;
907
- write ! ( f, "{value}" ) ?;
910
+ if let PatRangeBoundary :: Finite ( value) = & self . lo {
911
+ write ! ( f, "{value}" ) ?;
912
+ }
908
913
write ! ( f, "{}" , self . end) ?;
909
- let PatRangeBoundary :: Finite ( value) = & self . hi ;
910
- write ! ( f, "{value}" ) ?;
914
+ if let PatRangeBoundary :: Finite ( value) = & self . hi {
915
+ write ! ( f, "{value}" ) ?;
916
+ }
911
917
Ok ( ( ) )
912
918
}
913
919
}
@@ -917,38 +923,49 @@ impl<'tcx> fmt::Display for PatRange<'tcx> {
917
923
#[ derive( Copy , Clone , Debug , PartialEq , HashStable , TypeVisitable ) ]
918
924
pub enum PatRangeBoundary < ' tcx > {
919
925
Finite ( mir:: Const < ' tcx > ) ,
926
+ NegInfinity ,
927
+ PosInfinity ,
920
928
}
921
929
922
930
impl < ' tcx > PatRangeBoundary < ' tcx > {
923
931
#[ inline]
924
- pub fn lower_bound ( ty : Ty < ' tcx > , tcx : TyCtxt < ' tcx > ) -> Self {
925
- // Unwrap is ok because the type is known to be numeric.
926
- let c = ty. numeric_min_val ( tcx) . unwrap ( ) ;
927
- let value = mir:: Const :: from_ty_const ( c, tcx) ;
928
- Self :: Finite ( value)
932
+ pub fn is_finite ( self ) -> bool {
933
+ matches ! ( self , Self :: Finite ( ..) )
929
934
}
930
935
#[ inline]
931
- pub fn upper_bound ( ty : Ty < ' tcx > , tcx : TyCtxt < ' tcx > ) -> Self {
932
- // Unwrap is ok because the type is known to be numeric.
933
- let c = ty . numeric_max_val ( tcx ) . unwrap ( ) ;
934
- let value = mir :: Const :: from_ty_const ( c , tcx ) ;
935
- Self :: Finite ( value )
936
+ pub fn as_finite ( self ) -> Option < mir :: Const < ' tcx > > {
937
+ match self {
938
+ Self :: Finite ( value ) => Some ( value ) ,
939
+ Self :: NegInfinity | Self :: PosInfinity => None ,
940
+ }
936
941
}
937
-
938
942
#[ inline]
939
- pub fn to_const ( self , _ty : Ty < ' tcx > , _tcx : TyCtxt < ' tcx > ) -> mir:: Const < ' tcx > {
943
+ pub fn to_const ( self , ty : Ty < ' tcx > , tcx : TyCtxt < ' tcx > ) -> mir:: Const < ' tcx > {
940
944
match self {
941
945
Self :: Finite ( value) => value,
946
+ Self :: NegInfinity => {
947
+ // Unwrap is ok because the type is known to be numeric.
948
+ let c = ty. numeric_min_val ( tcx) . unwrap ( ) ;
949
+ mir:: Const :: from_ty_const ( c, tcx)
950
+ }
951
+ Self :: PosInfinity => {
952
+ // Unwrap is ok because the type is known to be numeric.
953
+ let c = ty. numeric_max_val ( tcx) . unwrap ( ) ;
954
+ mir:: Const :: from_ty_const ( c, tcx)
955
+ }
942
956
}
943
957
}
944
- pub fn eval_bits (
945
- self ,
946
- _ty : Ty < ' tcx > ,
947
- tcx : TyCtxt < ' tcx > ,
948
- param_env : ty:: ParamEnv < ' tcx > ,
949
- ) -> u128 {
958
+ pub fn eval_bits ( self , ty : Ty < ' tcx > , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > ) -> u128 {
950
959
match self {
951
960
Self :: Finite ( value) => value. eval_bits ( tcx, param_env) ,
961
+ Self :: NegInfinity => {
962
+ // Unwrap is ok because the type is known to be numeric.
963
+ ty. numeric_min_and_max_as_bits ( tcx) . unwrap ( ) . 0
964
+ }
965
+ Self :: PosInfinity => {
966
+ // Unwrap is ok because the type is known to be numeric.
967
+ ty. numeric_min_and_max_as_bits ( tcx) . unwrap ( ) . 1
968
+ }
952
969
}
953
970
}
954
971
@@ -962,6 +979,12 @@ impl<'tcx> PatRangeBoundary<'tcx> {
962
979
) -> Option < Ordering > {
963
980
use PatRangeBoundary :: * ;
964
981
match ( self , other) {
982
+ // When comparing with infinities, we must remember that `0u8..` and `0u8..=255`
983
+ // describe the same range. These two shortcuts are ok, but for the rest we must check
984
+ // bit values.
985
+ ( PosInfinity , PosInfinity ) => return Some ( Ordering :: Equal ) ,
986
+ ( NegInfinity , NegInfinity ) => return Some ( Ordering :: Equal ) ,
987
+
965
988
// This code is hot when compiling matches with many ranges. So we
966
989
// special-case extraction of evaluated scalars for speed, for types where
967
990
// raw data comparisons are appropriate. E.g. `unicode-normalization` has
0 commit comments