@@ -470,20 +470,21 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
470
470
]
471
471
}
472
472
ty:: TyInt ( _) if exhaustive_integer_patterns => {
473
- let size = cx. tcx . layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( pcx. ty ) )
473
+ // FIXME(49937): refactor these bit manipulations into interpret.
474
+ let bits = cx. tcx . layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( pcx. ty ) )
474
475
. unwrap ( ) . size . bits ( ) as u128 ;
475
- let min = ( 1u128 << ( size - 1 ) ) . wrapping_neg ( ) ;
476
- let max = ( 1u128 << ( size - 1 ) ) . wrapping_sub ( 1 ) ;
476
+ let min = 1u128 << ( bits - 1 ) ;
477
+ let max = ( 1u128 << ( bits - 1 ) ) - 1 ;
477
478
value_constructors = true ;
478
479
vec ! [ ConstantRange ( ty:: Const :: from_bits( cx. tcx, min as u128 , pcx. ty) ,
479
480
ty:: Const :: from_bits( cx. tcx, max as u128 , pcx. ty) ,
480
481
RangeEnd :: Included ) ]
481
482
}
482
483
ty:: TyUint ( _) if exhaustive_integer_patterns => {
483
- let size = cx. tcx . layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( pcx. ty ) )
484
+ // FIXME(49937): refactor these bit manipulations into interpret.
485
+ let bits = cx. tcx . layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( pcx. ty ) )
484
486
. unwrap ( ) . size . bits ( ) as u32 ;
485
- let shift = 1u128 . overflowing_shl ( size) ;
486
- let max = shift. 0 . wrapping_sub ( 1 + ( shift. 1 as u128 ) ) ;
487
+ let max = ( !0u128 ) . wrapping_shr ( 128 - bits) ;
487
488
value_constructors = true ;
488
489
vec ! [ ConstantRange ( ty:: Const :: from_bits( cx. tcx, 0u128 , pcx. ty) ,
489
490
ty:: Const :: from_bits( cx. tcx, max as u128 , pcx. ty) ,
@@ -603,8 +604,12 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
603
604
}
604
605
605
606
/// An inclusive interval, used for precise integer exhaustiveness checking.
606
- /// `Interval`s always store a contiguous range of integers. That means that
607
- /// signed integers are offset (see `offset_sign`) by their minimum value.
607
+ /// `Interval`s always store a contiguous range of integers. This means that
608
+ /// signed values are encoded by offsetting them such that `0` represents the
609
+ /// minimum value for the integer, regardless of sign.
610
+ /// For example, the range `-128...127` is encoded as `0...255`.
611
+ /// This makes comparisons and arithmetic on interval endpoints much more
612
+ /// straightforward. See `offset_sign` for the conversion technique.
608
613
struct Interval < ' tcx > {
609
614
pub range : RangeInclusive < u128 > ,
610
615
pub ty : Ty < ' tcx > ,
@@ -661,10 +666,11 @@ impl<'tcx> Interval<'tcx> {
661
666
let ( lo, hi) = range. into_inner ( ) ;
662
667
match ty. sty {
663
668
ty:: TyInt ( _) => {
664
- let size = tcx. layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( ty) )
669
+ // FIXME(49937): refactor these bit manipulations into interpret.
670
+ let bits = tcx. layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( ty) )
665
671
. unwrap ( ) . size . bits ( ) as u128 ;
666
- let min = ( 1u128 << ( size - 1 ) ) . wrapping_neg ( ) ;
667
- let shift = 1u128 . overflowing_shl ( size as u32 ) ;
672
+ let min = 1u128 << ( bits - 1 ) ;
673
+ let shift = 1u128 . overflowing_shl ( bits as u32 ) ;
668
674
let mask = shift. 0 . wrapping_sub ( 1 + ( shift. 1 as u128 ) ) ;
669
675
if encode {
670
676
let offset = |x : u128 | x. wrapping_sub ( min) & mask;
0 commit comments