@@ -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`).
@@ -645,6 +647,12 @@ impl<'tcx> Constructor<'tcx> {
645
647
_ => None ,
646
648
}
647
649
}
650
+ fn as_bool ( & self ) -> Option < bool > {
651
+ match self {
652
+ Bool ( b) => Some ( * b) ,
653
+ _ => None ,
654
+ }
655
+ }
648
656
fn as_int_range ( & self ) -> Option < & IntRange > {
649
657
match self {
650
658
IntRange ( range) => Some ( range) ,
@@ -689,10 +697,11 @@ impl<'tcx> Constructor<'tcx> {
689
697
_ => bug ! ( "Unexpected type for `Single` constructor: {:?}" , pcx. ty) ,
690
698
} ,
691
699
Slice ( slice) => slice. arity ( ) ,
692
- Str ( ..)
700
+ Bool ( ..)
701
+ | IntRange ( ..)
693
702
| F32Range ( ..)
694
703
| F64Range ( ..)
695
- | IntRange ( ..)
704
+ | Str ( ..)
696
705
| Opaque
697
706
| NonExhaustive
698
707
| Hidden
@@ -808,6 +817,7 @@ impl<'tcx> Constructor<'tcx> {
808
817
809
818
( Single , Single ) => true ,
810
819
( Variant ( self_id) , Variant ( other_id) ) => self_id == other_id,
820
+ ( Bool ( self_b) , Bool ( other_b) ) => self_b == other_b,
811
821
812
822
( IntRange ( self_range) , IntRange ( other_range) ) => self_range. is_subrange ( other_range) ,
813
823
( F32Range ( self_from, self_to, self_end) , F32Range ( other_from, other_to, other_end) ) => {
@@ -860,9 +870,10 @@ pub(super) enum ConstructorSet {
860
870
hidden_variants : Vec < VariantIdx > ,
861
871
non_exhaustive : bool ,
862
872
} ,
873
+ /// Booleans.
874
+ Bool ,
863
875
/// The type is spanned by integer values. The range or ranges give the set of allowed values.
864
876
/// The second range is only useful for `char`.
865
- /// This is reused for bool. FIXME: don't.
866
877
/// `non_exhaustive` is used when the range is not allowed to be matched exhaustively (that's
867
878
/// for usize/isize).
868
879
Integers { range_1 : IntRange , range_2 : Option < IntRange > , non_exhaustive : bool } ,
@@ -912,9 +923,7 @@ impl ConstructorSet {
912
923
// Invariant: this is `Uninhabited` if and only if the type is uninhabited (as determined by
913
924
// `cx.is_uninhabited()`).
914
925
match ty. kind ( ) {
915
- ty:: Bool => {
916
- Self :: Integers { range_1 : make_range ( 0 , 1 ) , range_2 : None , non_exhaustive : false }
917
- }
926
+ ty:: Bool => Self :: Bool ,
918
927
ty:: Char => {
919
928
// The valid Unicode Scalar Value ranges.
920
929
Self :: Integers {
@@ -1074,6 +1083,27 @@ impl ConstructorSet {
1074
1083
missing. push ( NonExhaustive ) ;
1075
1084
}
1076
1085
}
1086
+ ConstructorSet :: Bool => {
1087
+ let mut seen_false = false ;
1088
+ let mut seen_true = false ;
1089
+ for b in seen. map ( |ctor| ctor. as_bool ( ) . unwrap ( ) ) {
1090
+ if b {
1091
+ seen_true = true ;
1092
+ } else {
1093
+ seen_false = true ;
1094
+ }
1095
+ }
1096
+ if seen_false {
1097
+ present. push ( Bool ( false ) ) ;
1098
+ } else {
1099
+ missing. push ( Bool ( false ) ) ;
1100
+ }
1101
+ if seen_true {
1102
+ present. push ( Bool ( true ) ) ;
1103
+ } else {
1104
+ missing. push ( Bool ( true ) ) ;
1105
+ }
1106
+ }
1077
1107
ConstructorSet :: Integers { range_1, range_2, non_exhaustive } => {
1078
1108
let seen_ranges: Vec < _ > =
1079
1109
seen. map ( |ctor| ctor. as_int_range ( ) . unwrap ( ) . clone ( ) ) . collect ( ) ;
@@ -1269,10 +1299,11 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1269
1299
}
1270
1300
_ => bug ! ( "bad slice pattern {:?} {:?}" , constructor, pcx) ,
1271
1301
} ,
1272
- Str ( ..)
1302
+ Bool ( ..)
1303
+ | IntRange ( ..)
1273
1304
| F32Range ( ..)
1274
1305
| F64Range ( ..)
1275
- | IntRange ( ..)
1306
+ | Str ( ..)
1276
1307
| Opaque
1277
1308
| NonExhaustive
1278
1309
| Hidden
@@ -1400,7 +1431,14 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
1400
1431
}
1401
1432
PatKind :: Constant { value } => {
1402
1433
match pat. ty . kind ( ) {
1403
- ty:: Bool | ty:: Char | ty:: Int ( _) | ty:: Uint ( _) => {
1434
+ ty:: Bool => {
1435
+ ctor = match value. try_eval_bool ( cx. tcx , cx. param_env ) {
1436
+ Some ( b) => Bool ( b) ,
1437
+ None => Opaque ,
1438
+ } ;
1439
+ fields = Fields :: empty ( ) ;
1440
+ }
1441
+ ty:: Char | ty:: Int ( _) | ty:: Uint ( _) => {
1404
1442
ctor = match value. try_eval_bits ( cx. tcx , cx. param_env ) {
1405
1443
Some ( bits) => IntRange ( IntRange :: from_bits ( cx. tcx , pat. ty , bits) ) ,
1406
1444
None => Opaque ,
@@ -1679,9 +1717,11 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> {
1679
1717
}
1680
1718
write ! ( f, "]" )
1681
1719
}
1720
+ Bool ( b) => write ! ( f, "{b}" ) ,
1721
+ // Best-effort, will render signed ranges incorrectly
1722
+ IntRange ( range) => write ! ( f, "{range:?}" ) ,
1682
1723
F32Range ( lo, hi, end) => write ! ( f, "{lo}{end}{hi}" ) ,
1683
1724
F64Range ( lo, hi, end) => write ! ( f, "{lo}{end}{hi}" ) ,
1684
- IntRange ( range) => write ! ( f, "{range:?}" ) , // Best-effort, will render e.g. `false` as `0..=0`
1685
1725
Str ( value) => write ! ( f, "{value}" ) ,
1686
1726
Opaque => write ! ( f, "<constant pattern>" ) ,
1687
1727
Or => {
@@ -1731,10 +1771,13 @@ impl<'tcx> WitnessPat<'tcx> {
1731
1771
self . ty
1732
1772
}
1733
1773
1774
+ /// Convert back to a `thir::Pat` for diagnostic purposes.
1734
1775
pub ( crate ) fn to_pat ( & self , cx : & MatchCheckCtxt < ' _ , ' tcx > ) -> Pat < ' tcx > {
1735
1776
let is_wildcard = |pat : & Pat < ' _ > | matches ! ( pat. kind, PatKind :: Wild ) ;
1736
1777
let mut subpatterns = self . iter_fields ( ) . map ( |p| Box :: new ( p. to_pat ( cx) ) ) ;
1737
1778
let kind = match & self . ctor {
1779
+ Bool ( b) => PatKind :: Constant { value : mir:: Const :: from_bool ( cx. tcx , * b) } ,
1780
+ IntRange ( range) => return range. to_pat ( cx. tcx , self . ty ) ,
1738
1781
Single | Variant ( _) => match self . ty . kind ( ) {
1739
1782
ty:: Tuple ( ..) => PatKind :: Leaf {
1740
1783
subpatterns : subpatterns
@@ -1804,7 +1847,6 @@ impl<'tcx> WitnessPat<'tcx> {
1804
1847
}
1805
1848
}
1806
1849
& Str ( value) => PatKind :: Constant { value } ,
1807
- IntRange ( range) => return range. to_pat ( cx. tcx , self . ty ) ,
1808
1850
Wildcard | NonExhaustive | Hidden => PatKind :: Wild ,
1809
1851
Missing { .. } => bug ! (
1810
1852
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
0 commit comments