@@ -483,11 +483,11 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
483
483
ty:: TyUint ( _) if exhaustive_integer_patterns => {
484
484
// FIXME(49937): refactor these bit manipulations into interpret.
485
485
let bits = cx. tcx . layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( pcx. ty ) )
486
- . unwrap ( ) . size . bits ( ) as u32 ;
487
- let max = ( !0u128 ) . wrapping_shr ( 128 - bits) ;
486
+ . unwrap ( ) . size . bits ( ) as u128 ;
487
+ let max = !0u128 >> ( 128 - bits) ;
488
488
value_constructors = true ;
489
- vec ! [ ConstantRange ( ty:: Const :: from_bits( cx. tcx, 0u128 , pcx. ty) ,
490
- ty:: Const :: from_bits( cx. tcx, max as u128 , pcx. ty) ,
489
+ vec ! [ ConstantRange ( ty:: Const :: from_bits( cx. tcx, 0 , pcx. ty) ,
490
+ ty:: Const :: from_bits( cx. tcx, max, pcx. ty) ,
491
491
RangeEnd :: Included ) ]
492
492
}
493
493
_ => {
@@ -604,21 +604,21 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
604
604
}
605
605
606
606
/// An inclusive interval, used for precise integer exhaustiveness checking.
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`.
607
+ /// `IntRange `s always store a contiguous range. This means that values are
608
+ /// encoded such that `0` encodes the minimum value for the integer,
609
+ /// regardless of the signedness .
610
+ /// For example, the pattern `-128...127i8 ` is encoded as `0..= 255`.
611
611
/// This makes comparisons and arithmetic on interval endpoints much more
612
- /// straightforward. See `offset_sign` for the conversion technique .
613
- struct Interval < ' tcx > {
612
+ /// straightforward. See `encode` and `decode` for details .
613
+ struct IntRange < ' tcx > {
614
614
pub range : RangeInclusive < u128 > ,
615
615
pub ty : Ty < ' tcx > ,
616
616
}
617
617
618
- impl < ' tcx > Interval < ' tcx > {
618
+ impl < ' tcx > IntRange < ' tcx > {
619
619
fn from_ctor ( tcx : TyCtxt < ' _ , ' tcx , ' tcx > ,
620
620
ctor : & Constructor < ' tcx > )
621
- -> Option < Interval < ' tcx > > {
621
+ -> Option < IntRange < ' tcx > > {
622
622
match ctor {
623
623
ConstantRange ( lo, hi, end) => {
624
624
assert_eq ! ( lo. ty, hi. ty) ;
@@ -627,13 +627,13 @@ impl<'tcx> Interval<'tcx> {
627
627
if let Some ( hi) = hi. assert_bits ( ty) {
628
628
// Perform a shift if the underlying types are signed,
629
629
// which makes the interval arithmetic simpler.
630
- let ( lo, hi) = Self :: offset_sign ( tcx, ty, lo..=hi, true ) ;
630
+ let ( lo, hi) = Self :: encode ( tcx, ty, lo..=hi) ;
631
631
// Make sure the interval is well-formed.
632
632
return if lo > hi || lo == hi && * end == RangeEnd :: Excluded {
633
633
None
634
634
} else {
635
635
let offset = ( * end == RangeEnd :: Excluded ) as u128 ;
636
- Some ( Interval { range : lo..=( hi - offset) , ty } )
636
+ Some ( IntRange { range : lo..=( hi - offset) , ty } )
637
637
} ;
638
638
}
639
639
}
@@ -642,8 +642,8 @@ impl<'tcx> Interval<'tcx> {
642
642
ConstantValue ( val) => {
643
643
let ty = val. ty ;
644
644
if let Some ( val) = val. assert_bits ( ty) {
645
- let ( lo, hi) = Self :: offset_sign ( tcx, ty, val..=val, true ) ;
646
- Some ( Interval { range : lo..=hi, ty } )
645
+ let ( lo, hi) = Self :: encode ( tcx, ty, val..=val) ;
646
+ Some ( IntRange { range : lo..=hi, ty } )
647
647
} else {
648
648
None
649
649
}
@@ -654,11 +654,11 @@ impl<'tcx> Interval<'tcx> {
654
654
}
655
655
}
656
656
657
- fn offset_sign ( tcx : TyCtxt < ' _ , ' tcx , ' tcx > ,
658
- ty : Ty < ' tcx > ,
659
- range : RangeInclusive < u128 > ,
660
- encode : bool )
661
- -> ( u128 , u128 ) {
657
+ fn convert ( tcx : TyCtxt < ' _ , ' tcx , ' tcx > ,
658
+ ty : Ty < ' tcx > ,
659
+ range : RangeInclusive < u128 > ,
660
+ encode : bool )
661
+ -> ( u128 , u128 ) {
662
662
// We ensure that all integer values are contiguous: that is, that their
663
663
// minimum value is represented by 0, so that comparisons and increments/
664
664
// decrements on interval endpoints work consistently whether the endpoints
@@ -670,13 +670,14 @@ impl<'tcx> Interval<'tcx> {
670
670
let bits = tcx. layout_of ( ty:: ParamEnv :: reveal_all ( ) . and ( ty) )
671
671
. unwrap ( ) . size . bits ( ) as u128 ;
672
672
let min = 1u128 << ( bits - 1 ) ;
673
- let shift = 1u128 . overflowing_shl ( bits as u32 ) ;
674
- let mask = shift. 0 . wrapping_sub ( 1 + ( shift. 1 as u128 ) ) ;
673
+ let mask = !0u128 >> ( 128 - bits) ;
675
674
if encode {
676
675
let offset = |x : u128 | x. wrapping_sub ( min) & mask;
677
676
( offset ( lo) , offset ( hi) )
678
677
} else {
679
678
let offset = |x : u128 | {
679
+ // FIXME: this shouldn't be necessary once `print_miri_value`
680
+ // sign-extends `TyInt`.
680
681
interpret:: sign_extend ( tcx, x. wrapping_add ( min) & mask, ty)
681
682
. expect ( "layout error for TyInt" )
682
683
} ;
@@ -686,10 +687,24 @@ impl<'tcx> Interval<'tcx> {
686
687
ty:: TyUint ( _) | ty:: TyChar => {
687
688
( lo, hi)
688
689
}
689
- _ => bug ! ( "`Interval ` should only contain integer types" )
690
+ _ => bug ! ( "`IntRange ` should only contain integer types" )
690
691
}
691
692
}
692
693
694
+ fn encode ( tcx : TyCtxt < ' _ , ' tcx , ' tcx > ,
695
+ ty : Ty < ' tcx > ,
696
+ range : RangeInclusive < u128 > )
697
+ -> ( u128 , u128 ) {
698
+ Self :: convert ( tcx, ty, range, true )
699
+ }
700
+
701
+ fn decode ( tcx : TyCtxt < ' _ , ' tcx , ' tcx > ,
702
+ ty : Ty < ' tcx > ,
703
+ range : RangeInclusive < u128 > )
704
+ -> ( u128 , u128 ) {
705
+ Self :: convert ( tcx, ty, range, false )
706
+ }
707
+
693
708
fn into_inner ( self ) -> ( u128 , u128 ) {
694
709
self . range . into_inner ( )
695
710
}
@@ -702,10 +717,10 @@ fn ranges_subtract_pattern<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
702
717
pat_ctor : & Constructor < ' tcx > ,
703
718
ranges : Vec < Constructor < ' tcx > > )
704
719
-> Vec < Constructor < ' tcx > > {
705
- if let Some ( pat_interval) = Interval :: from_ctor ( cx. tcx , pat_ctor) {
720
+ if let Some ( pat_interval) = IntRange :: from_ctor ( cx. tcx , pat_ctor) {
706
721
let mut remaining_ranges = vec ! [ ] ;
707
722
let mut ranges: Vec < _ > = ranges. into_iter ( ) . filter_map ( |r| {
708
- Interval :: from_ctor ( cx. tcx , & r) . map ( |i| i. into_inner ( ) )
723
+ IntRange :: from_ctor ( cx. tcx , & r) . map ( |i| i. into_inner ( ) )
709
724
} ) . collect ( ) ;
710
725
let ty = pat_interval. ty ;
711
726
let ( pat_interval_lo, pat_interval_hi) = pat_interval. into_inner ( ) ;
@@ -729,7 +744,7 @@ fn ranges_subtract_pattern<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
729
744
}
730
745
// Convert the remaining ranges from pairs to inclusive `ConstantRange`s.
731
746
remaining_ranges. into_iter ( ) . map ( |r| {
732
- let ( lo, hi) = Interval :: offset_sign ( cx. tcx , ty, r, false ) ;
747
+ let ( lo, hi) = IntRange :: decode ( cx. tcx , ty, r) ;
733
748
ConstantRange ( ty:: Const :: from_bits ( cx. tcx , lo, ty) ,
734
749
ty:: Const :: from_bits ( cx. tcx , hi, ty) ,
735
750
RangeEnd :: Included )
0 commit comments