@@ -112,7 +112,7 @@ pub(crate) struct IntRange {
112
112
impl IntRange {
113
113
#[ inline]
114
114
fn is_integral ( ty : Ty < ' _ > ) -> bool {
115
- matches ! ( ty. kind( ) , ty:: Char | ty:: Int ( _) | ty:: Uint ( _) | ty :: Bool )
115
+ matches ! ( ty. kind( ) , ty:: Char | ty:: Int ( _) | ty:: Uint ( _) )
116
116
}
117
117
118
118
fn is_singleton ( & self ) -> bool {
@@ -363,8 +363,8 @@ impl IntRange {
363
363
}
364
364
}
365
365
366
- /// Note: this is often not what we want: e.g. `false` is converted into the range `0..=0` and
367
- /// would be displayed as such. To render properly, convert to a pattern first.
366
+ /// Note: this will render signed ranges incorrectly. To render properly, convert to a pattern
367
+ /// first.
368
368
impl fmt:: Debug for IntRange {
369
369
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
370
370
let ( lo, hi) = self . boundaries ( ) ;
@@ -605,6 +605,8 @@ pub(super) enum Constructor<'tcx> {
605
605
Single ,
606
606
/// Enum variants.
607
607
Variant ( VariantIdx ) ,
608
+ /// Booleans
609
+ Bool ( bool ) ,
608
610
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
609
611
IntRange ( IntRange ) ,
610
612
/// Ranges of floating-point literal values (`2.0..=5.2`).
@@ -652,6 +654,12 @@ impl<'tcx> Constructor<'tcx> {
652
654
_ => None ,
653
655
}
654
656
}
657
+ fn as_bool ( & self ) -> Option < bool > {
658
+ match self {
659
+ Bool ( b) => Some ( * b) ,
660
+ _ => None ,
661
+ }
662
+ }
655
663
fn as_int_range ( & self ) -> Option < & IntRange > {
656
664
match self {
657
665
IntRange ( range) => Some ( range) ,
@@ -696,10 +704,11 @@ impl<'tcx> Constructor<'tcx> {
696
704
_ => bug ! ( "Unexpected type for `Single` constructor: {:?}" , pcx. ty) ,
697
705
} ,
698
706
Slice ( slice) => slice. arity ( ) ,
699
- Str ( ..)
707
+ Bool ( ..)
708
+ | IntRange ( ..)
700
709
| F32Range ( ..)
701
710
| F64Range ( ..)
702
- | IntRange ( ..)
711
+ | Str ( ..)
703
712
| Opaque
704
713
| NonExhaustive
705
714
| Hidden
@@ -821,6 +830,7 @@ impl<'tcx> Constructor<'tcx> {
821
830
822
831
( Single , Single ) => true ,
823
832
( Variant ( self_id) , Variant ( other_id) ) => self_id == other_id,
833
+ ( Bool ( self_b) , Bool ( other_b) ) => self_b == other_b,
824
834
825
835
( IntRange ( self_range) , IntRange ( other_range) ) => self_range. is_subrange ( other_range) ,
826
836
( F32Range ( self_from, self_to, self_end) , F32Range ( other_from, other_to, other_end) ) => {
@@ -873,9 +883,10 @@ pub(super) enum ConstructorSet {
873
883
hidden_variants : Vec < VariantIdx > ,
874
884
non_exhaustive : bool ,
875
885
} ,
886
+ /// Booleans.
887
+ Bool ,
876
888
/// The type is spanned by integer values. The range or ranges give the set of allowed values.
877
889
/// The second range is only useful for `char`.
878
- /// This is reused for bool. FIXME: don't.
879
890
/// `non_exhaustive` is used when the range is not allowed to be matched exhaustively (that's
880
891
/// for usize/isize).
881
892
Integers { range_1 : IntRange , range_2 : Option < IntRange > , non_exhaustive : bool } ,
@@ -927,9 +938,7 @@ impl ConstructorSet {
927
938
// Invariant: this is `Uninhabited` if and only if the type is uninhabited (as determined by
928
939
// `cx.is_uninhabited()`).
929
940
match ty. kind ( ) {
930
- ty:: Bool => {
931
- Self :: Integers { range_1 : make_range ( 0 , 1 ) , range_2 : None , non_exhaustive : false }
932
- }
941
+ ty:: Bool => Self :: Bool ,
933
942
ty:: Char => {
934
943
// The valid Unicode Scalar Value ranges.
935
944
Self :: Integers {
@@ -1091,6 +1100,19 @@ impl ConstructorSet {
1091
1100
missing. push ( NonExhaustive ) ;
1092
1101
}
1093
1102
}
1103
+ ConstructorSet :: Bool => {
1104
+ let mut seen_bools = [ false , false ] ;
1105
+ for b in seen. map ( |ctor| ctor. as_bool ( ) . unwrap ( ) ) {
1106
+ seen_bools[ b as usize ] = true ;
1107
+ }
1108
+ for b in [ true , false ] {
1109
+ if seen_bools[ b as usize ] {
1110
+ present. push ( Bool ( b) ) ;
1111
+ } else {
1112
+ missing. push ( Bool ( b) ) ;
1113
+ }
1114
+ }
1115
+ }
1094
1116
ConstructorSet :: Integers { range_1, range_2, non_exhaustive } => {
1095
1117
let seen_ranges: Vec < _ > =
1096
1118
seen. map ( |ctor| ctor. as_int_range ( ) . unwrap ( ) . clone ( ) ) . collect ( ) ;
@@ -1286,10 +1308,11 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1286
1308
}
1287
1309
_ => bug ! ( "bad slice pattern {:?} {:?}" , constructor, pcx) ,
1288
1310
} ,
1289
- Str ( ..)
1311
+ Bool ( ..)
1312
+ | IntRange ( ..)
1290
1313
| F32Range ( ..)
1291
1314
| F64Range ( ..)
1292
- | IntRange ( ..)
1315
+ | Str ( ..)
1293
1316
| Opaque
1294
1317
| NonExhaustive
1295
1318
| Hidden
@@ -1430,7 +1453,14 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
1430
1453
}
1431
1454
PatKind :: Constant { value } => {
1432
1455
match pat. ty . kind ( ) {
1433
- ty:: Bool | ty:: Char | ty:: Int ( _) | ty:: Uint ( _) => {
1456
+ ty:: Bool => {
1457
+ ctor = match value. try_eval_bool ( cx. tcx , cx. param_env ) {
1458
+ Some ( b) => Bool ( b) ,
1459
+ None => Opaque ,
1460
+ } ;
1461
+ fields = Fields :: empty ( ) ;
1462
+ }
1463
+ ty:: Char | ty:: Int ( _) | ty:: Uint ( _) => {
1434
1464
ctor = match value. try_eval_bits ( cx. tcx , cx. param_env ) {
1435
1465
Some ( bits) => IntRange ( IntRange :: from_bits ( cx. tcx , pat. ty , bits) ) ,
1436
1466
None => Opaque ,
@@ -1605,8 +1635,9 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
1605
1635
}
1606
1636
}
1607
1637
}
1608
- & Str ( value ) => PatKind :: Constant { value } ,
1638
+ Bool ( b ) => PatKind :: Constant { value : mir :: Const :: from_bool ( cx . tcx , * b ) } ,
1609
1639
IntRange ( range) => return range. to_pat ( cx. tcx , self . ty ) ,
1640
+ & Str ( value) => PatKind :: Constant { value } ,
1610
1641
Wildcard | NonExhaustive | Hidden => PatKind :: Wild ,
1611
1642
Missing { .. } => bug ! (
1612
1643
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
@@ -1787,9 +1818,11 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> {
1787
1818
}
1788
1819
write ! ( f, "]" )
1789
1820
}
1821
+ Bool ( b) => write ! ( f, "{b}" ) ,
1822
+ // Best-effort, will render signed ranges incorrectly
1823
+ IntRange ( range) => write ! ( f, "{range:?}" ) ,
1790
1824
F32Range ( lo, hi, end) => write ! ( f, "{lo}{end}{hi}" ) ,
1791
1825
F64Range ( lo, hi, end) => write ! ( f, "{lo}{end}{hi}" ) ,
1792
- IntRange ( range) => write ! ( f, "{range:?}" ) , // Best-effort, will render e.g. `false` as `0..=0`
1793
1826
Str ( value) => write ! ( f, "{value}" ) ,
1794
1827
Opaque => write ! ( f, "<constant pattern>" ) ,
1795
1828
Or => {
0 commit comments