@@ -110,7 +110,7 @@ pub(crate) struct IntRange {
110
110
impl IntRange {
111
111
#[ inline]
112
112
pub ( super ) fn is_integral ( ty : Ty < ' _ > ) -> bool {
113
- matches ! ( ty. kind( ) , ty:: Char | ty:: Int ( _) | ty:: Uint ( _) | ty :: Bool )
113
+ matches ! ( ty. kind( ) , ty:: Char | ty:: Int ( _) | ty:: Uint ( _) )
114
114
}
115
115
116
116
pub ( super ) fn is_singleton ( & self ) -> bool {
@@ -299,8 +299,8 @@ impl IntRange {
299
299
}
300
300
}
301
301
302
- /// Note: this is often not what we want: e.g. `false` is converted into the range `0..=0` and
303
- /// would be displayed as such. To render properly, convert to a pattern first.
302
+ /// Note: this will render signed ranges incorrectly. To render properly, convert to a pattern
303
+ /// first.
304
304
impl fmt:: Debug for IntRange {
305
305
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
306
306
let ( lo, hi) = self . boundaries ( ) ;
@@ -541,6 +541,8 @@ pub(super) enum Constructor<'tcx> {
541
541
Single ,
542
542
/// Enum variants.
543
543
Variant ( VariantIdx ) ,
544
+ /// Booleans
545
+ Bool ( bool ) ,
544
546
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
545
547
IntRange ( IntRange ) ,
546
548
/// Ranges of floating-point literal values (`2.0..=5.2`).
@@ -581,6 +583,12 @@ impl<'tcx> Constructor<'tcx> {
581
583
_ => None ,
582
584
}
583
585
}
586
+ fn as_bool ( & self ) -> Option < bool > {
587
+ match self {
588
+ Bool ( b) => Some ( * b) ,
589
+ _ => None ,
590
+ }
591
+ }
584
592
pub ( super ) fn as_int_range ( & self ) -> Option < & IntRange > {
585
593
match self {
586
594
IntRange ( range) => Some ( range) ,
@@ -625,10 +633,11 @@ impl<'tcx> Constructor<'tcx> {
625
633
_ => bug ! ( "Unexpected type for `Single` constructor: {:?}" , pcx. ty) ,
626
634
} ,
627
635
Slice ( slice) => slice. arity ( ) ,
628
- Str ( ..)
636
+ Bool ( ..)
637
+ | IntRange ( ..)
629
638
| F32Range ( ..)
630
639
| F64Range ( ..)
631
- | IntRange ( ..)
640
+ | Str ( ..)
632
641
| Opaque
633
642
| NonExhaustive
634
643
| Hidden
@@ -744,6 +753,7 @@ impl<'tcx> Constructor<'tcx> {
744
753
745
754
( Single , Single ) => true ,
746
755
( Variant ( self_id) , Variant ( other_id) ) => self_id == other_id,
756
+ ( Bool ( self_b) , Bool ( other_b) ) => self_b == other_b,
747
757
748
758
( IntRange ( self_range) , IntRange ( other_range) ) => self_range. is_subrange ( other_range) ,
749
759
( F32Range ( self_from, self_to, self_end) , F32Range ( other_from, other_to, other_end) ) => {
@@ -796,9 +806,10 @@ pub(super) enum ConstructorSet {
796
806
hidden_variants : Vec < VariantIdx > ,
797
807
non_exhaustive : bool ,
798
808
} ,
809
+ /// Booleans.
810
+ Bool ,
799
811
/// The type is spanned by integer values. The range or ranges give the set of allowed values.
800
812
/// The second range is only useful for `char`.
801
- /// This is reused for bool. FIXME: don't.
802
813
/// `non_exhaustive` is used when the range is not allowed to be matched exhaustively (that's
803
814
/// for usize/isize).
804
815
Integers { range_1 : IntRange , range_2 : Option < IntRange > , non_exhaustive : bool } ,
@@ -848,9 +859,7 @@ impl ConstructorSet {
848
859
// Invariant: this is `Uninhabited` if and only if the type is uninhabited (as determined by
849
860
// `cx.is_uninhabited()`).
850
861
match ty. kind ( ) {
851
- ty:: Bool => {
852
- Self :: Integers { range_1 : make_range ( 0 , 1 ) , range_2 : None , non_exhaustive : false }
853
- }
862
+ ty:: Bool => Self :: Bool ,
854
863
ty:: Char => {
855
864
// The valid Unicode Scalar Value ranges.
856
865
Self :: Integers {
@@ -1010,6 +1019,27 @@ impl ConstructorSet {
1010
1019
missing. push ( NonExhaustive ) ;
1011
1020
}
1012
1021
}
1022
+ ConstructorSet :: Bool => {
1023
+ let mut seen_false = false ;
1024
+ let mut seen_true = false ;
1025
+ for b in seen. map ( |ctor| ctor. as_bool ( ) . unwrap ( ) ) {
1026
+ if b {
1027
+ seen_true = true ;
1028
+ } else {
1029
+ seen_false = true ;
1030
+ }
1031
+ }
1032
+ if seen_false {
1033
+ present. push ( Bool ( false ) ) ;
1034
+ } else {
1035
+ missing. push ( Bool ( false ) ) ;
1036
+ }
1037
+ if seen_true {
1038
+ present. push ( Bool ( true ) ) ;
1039
+ } else {
1040
+ missing. push ( Bool ( true ) ) ;
1041
+ }
1042
+ }
1013
1043
ConstructorSet :: Integers { range_1, range_2, non_exhaustive } => {
1014
1044
let seen_ranges: Vec < _ > =
1015
1045
seen. map ( |ctor| ctor. as_int_range ( ) . unwrap ( ) . clone ( ) ) . collect ( ) ;
@@ -1205,10 +1235,11 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1205
1235
}
1206
1236
_ => bug ! ( "bad slice pattern {:?} {:?}" , constructor, pcx) ,
1207
1237
} ,
1208
- Str ( ..)
1238
+ Bool ( ..)
1239
+ | IntRange ( ..)
1209
1240
| F32Range ( ..)
1210
1241
| F64Range ( ..)
1211
- | IntRange ( ..)
1242
+ | Str ( ..)
1212
1243
| Opaque
1213
1244
| NonExhaustive
1214
1245
| Hidden
@@ -1337,7 +1368,14 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
1337
1368
}
1338
1369
PatKind :: Constant { value } => {
1339
1370
match pat. ty . kind ( ) {
1340
- ty:: Bool | ty:: Char | ty:: Int ( _) | ty:: Uint ( _) => {
1371
+ ty:: Bool => {
1372
+ ctor = match value. try_eval_bool ( cx. tcx , cx. param_env ) {
1373
+ Some ( b) => Bool ( b) ,
1374
+ None => Opaque ,
1375
+ } ;
1376
+ fields = Fields :: empty ( ) ;
1377
+ }
1378
+ ty:: Char | ty:: Int ( _) | ty:: Uint ( _) => {
1341
1379
ctor = match value. try_eval_bits ( cx. tcx , cx. param_env ) {
1342
1380
Some ( bits) => IntRange ( IntRange :: from_bits ( cx. tcx , pat. ty , bits) ) ,
1343
1381
None => Opaque ,
@@ -1616,9 +1654,11 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> {
1616
1654
}
1617
1655
write ! ( f, "]" )
1618
1656
}
1657
+ Bool ( b) => write ! ( f, "{b}" ) ,
1658
+ // Best-effort, will render signed ranges incorrectly
1659
+ IntRange ( range) => write ! ( f, "{range:?}" ) ,
1619
1660
F32Range ( lo, hi, end) => write ! ( f, "{lo}{end}{hi}" ) ,
1620
1661
F64Range ( lo, hi, end) => write ! ( f, "{lo}{end}{hi}" ) ,
1621
- IntRange ( range) => write ! ( f, "{range:?}" ) , // Best-effort, will render e.g. `false` as `0..=0`
1622
1662
Str ( value) => write ! ( f, "{value}" ) ,
1623
1663
Opaque => write ! ( f, "<constant pattern>" ) ,
1624
1664
Or => {
@@ -1668,10 +1708,13 @@ impl<'tcx> WitnessPat<'tcx> {
1668
1708
self . ty
1669
1709
}
1670
1710
1711
+ /// Convert back to a `thir::Pat` for diagnostic purposes.
1671
1712
pub ( crate ) fn to_pat ( & self , cx : & MatchCheckCtxt < ' _ , ' tcx > ) -> Pat < ' tcx > {
1672
1713
let is_wildcard = |pat : & Pat < ' _ > | matches ! ( pat. kind, PatKind :: Wild ) ;
1673
1714
let mut subpatterns = self . iter_fields ( ) . map ( |p| Box :: new ( p. to_pat ( cx) ) ) ;
1674
1715
let kind = match & self . ctor {
1716
+ Bool ( b) => PatKind :: Constant { value : mir:: Const :: from_bool ( cx. tcx , * b) } ,
1717
+ IntRange ( range) => return range. to_pat ( cx. tcx , self . ty ) ,
1675
1718
Single | Variant ( _) => match self . ty . kind ( ) {
1676
1719
ty:: Tuple ( ..) => PatKind :: Leaf {
1677
1720
subpatterns : subpatterns
@@ -1741,7 +1784,6 @@ impl<'tcx> WitnessPat<'tcx> {
1741
1784
}
1742
1785
}
1743
1786
& Str ( value) => PatKind :: Constant { value } ,
1744
- IntRange ( range) => return range. to_pat ( cx. tcx , self . ty ) ,
1745
1787
Wildcard | NonExhaustive | Hidden => PatKind :: Wild ,
1746
1788
Missing { .. } => bug ! (
1747
1789
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
0 commit comments