@@ -110,7 +110,7 @@ pub(crate) struct IntRange {
110110impl IntRange {
111111 #[ inline]
112112 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 ( _) )
114114 }
115115
116116 pub ( super ) fn is_singleton ( & self ) -> bool {
@@ -299,8 +299,8 @@ impl IntRange {
299299 }
300300}
301301
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.
304304impl fmt:: Debug for IntRange {
305305 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
306306 let ( lo, hi) = self . boundaries ( ) ;
@@ -541,6 +541,8 @@ pub(super) enum Constructor<'tcx> {
541541 Single ,
542542 /// Enum variants.
543543 Variant ( VariantIdx ) ,
544+ /// Booleans
545+ Bool ( bool ) ,
544546 /// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
545547 IntRange ( IntRange ) ,
546548 /// Ranges of floating-point literal values (`2.0..=5.2`).
@@ -581,6 +583,12 @@ impl<'tcx> Constructor<'tcx> {
581583 _ => None ,
582584 }
583585 }
586+ fn as_bool ( & self ) -> Option < bool > {
587+ match self {
588+ Bool ( b) => Some ( * b) ,
589+ _ => None ,
590+ }
591+ }
584592 pub ( super ) fn as_int_range ( & self ) -> Option < & IntRange > {
585593 match self {
586594 IntRange ( range) => Some ( range) ,
@@ -625,10 +633,11 @@ impl<'tcx> Constructor<'tcx> {
625633 _ => bug ! ( "Unexpected type for `Single` constructor: {:?}" , pcx. ty) ,
626634 } ,
627635 Slice ( slice) => slice. arity ( ) ,
628- Str ( ..)
636+ Bool ( ..)
637+ | IntRange ( ..)
629638 | F32Range ( ..)
630639 | F64Range ( ..)
631- | IntRange ( ..)
640+ | Str ( ..)
632641 | Opaque
633642 | NonExhaustive
634643 | Hidden
@@ -744,6 +753,7 @@ impl<'tcx> Constructor<'tcx> {
744753
745754 ( Single , Single ) => true ,
746755 ( Variant ( self_id) , Variant ( other_id) ) => self_id == other_id,
756+ ( Bool ( self_b) , Bool ( other_b) ) => self_b == other_b,
747757
748758 ( IntRange ( self_range) , IntRange ( other_range) ) => self_range. is_subrange ( other_range) ,
749759 ( F32Range ( self_from, self_to, self_end) , F32Range ( other_from, other_to, other_end) ) => {
@@ -796,9 +806,10 @@ pub(super) enum ConstructorSet {
796806 hidden_variants : Vec < VariantIdx > ,
797807 non_exhaustive : bool ,
798808 } ,
809+ /// Booleans.
810+ Bool ,
799811 /// The type is spanned by integer values. The range or ranges give the set of allowed values.
800812 /// The second range is only useful for `char`.
801- /// This is reused for bool. FIXME: don't.
802813 /// `non_exhaustive` is used when the range is not allowed to be matched exhaustively (that's
803814 /// for usize/isize).
804815 Integers { range_1 : IntRange , range_2 : Option < IntRange > , non_exhaustive : bool } ,
@@ -848,9 +859,7 @@ impl ConstructorSet {
848859 // Invariant: this is `Uninhabited` if and only if the type is uninhabited (as determined by
849860 // `cx.is_uninhabited()`).
850861 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 ,
854863 ty:: Char => {
855864 // The valid Unicode Scalar Value ranges.
856865 Self :: Integers {
@@ -1010,6 +1019,27 @@ impl ConstructorSet {
10101019 missing. push ( NonExhaustive ) ;
10111020 }
10121021 }
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+ }
10131043 ConstructorSet :: Integers { range_1, range_2, non_exhaustive } => {
10141044 let seen_ranges: Vec < _ > =
10151045 seen. map ( |ctor| ctor. as_int_range ( ) . unwrap ( ) . clone ( ) ) . collect ( ) ;
@@ -1205,10 +1235,11 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
12051235 }
12061236 _ => bug ! ( "bad slice pattern {:?} {:?}" , constructor, pcx) ,
12071237 } ,
1208- Str ( ..)
1238+ Bool ( ..)
1239+ | IntRange ( ..)
12091240 | F32Range ( ..)
12101241 | F64Range ( ..)
1211- | IntRange ( ..)
1242+ | Str ( ..)
12121243 | Opaque
12131244 | NonExhaustive
12141245 | Hidden
@@ -1337,7 +1368,14 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
13371368 }
13381369 PatKind :: Constant { value } => {
13391370 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 ( _) => {
13411379 ctor = match value. try_eval_bits ( cx. tcx , cx. param_env ) {
13421380 Some ( bits) => IntRange ( IntRange :: from_bits ( cx. tcx , pat. ty , bits) ) ,
13431381 None => Opaque ,
@@ -1616,9 +1654,11 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> {
16161654 }
16171655 write ! ( f, "]" )
16181656 }
1657+ Bool ( b) => write ! ( f, "{b}" ) ,
1658+ // Best-effort, will render signed ranges incorrectly
1659+ IntRange ( range) => write ! ( f, "{range:?}" ) ,
16191660 F32Range ( lo, hi, end) => write ! ( f, "{lo}{end}{hi}" ) ,
16201661 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`
16221662 Str ( value) => write ! ( f, "{value}" ) ,
16231663 Opaque => write ! ( f, "<constant pattern>" ) ,
16241664 Or => {
@@ -1668,10 +1708,13 @@ impl<'tcx> WitnessPat<'tcx> {
16681708 self . ty
16691709 }
16701710
1711+ /// Convert back to a `thir::Pat` for diagnostic purposes.
16711712 pub ( crate ) fn to_pat ( & self , cx : & MatchCheckCtxt < ' _ , ' tcx > ) -> Pat < ' tcx > {
16721713 let is_wildcard = |pat : & Pat < ' _ > | matches ! ( pat. kind, PatKind :: Wild ) ;
16731714 let mut subpatterns = self . iter_fields ( ) . map ( |p| Box :: new ( p. to_pat ( cx) ) ) ;
16741715 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 ) ,
16751718 Single | Variant ( _) => match self . ty . kind ( ) {
16761719 ty:: Tuple ( ..) => PatKind :: Leaf {
16771720 subpatterns : subpatterns
@@ -1741,7 +1784,6 @@ impl<'tcx> WitnessPat<'tcx> {
17411784 }
17421785 }
17431786 & Str ( value) => PatKind :: Constant { value } ,
1744- IntRange ( range) => return range. to_pat ( cx. tcx , self . ty ) ,
17451787 Wildcard | NonExhaustive | Hidden => PatKind :: Wild ,
17461788 Missing { .. } => bug ! (
17471789 "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
0 commit comments