Skip to content

Commit 23a4ce8

Browse files
committed
Don't use IntRange for booleans
1 parent f7e5920 commit 23a4ce8

File tree

1 file changed

+47
-14
lines changed

1 file changed

+47
-14
lines changed

compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ pub(crate) struct IntRange {
112112
impl IntRange {
113113
#[inline]
114114
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(_))
116116
}
117117

118118
fn is_singleton(&self) -> bool {
@@ -363,8 +363,8 @@ impl IntRange {
363363
}
364364
}
365365

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.
368368
impl fmt::Debug for IntRange {
369369
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
370370
let (lo, hi) = self.boundaries();
@@ -605,6 +605,8 @@ pub(super) enum Constructor<'tcx> {
605605
Single,
606606
/// Enum variants.
607607
Variant(VariantIdx),
608+
/// Booleans
609+
Bool(bool),
608610
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
609611
IntRange(IntRange),
610612
/// Ranges of floating-point literal values (`2.0..=5.2`).
@@ -652,6 +654,12 @@ impl<'tcx> Constructor<'tcx> {
652654
_ => None,
653655
}
654656
}
657+
fn as_bool(&self) -> Option<bool> {
658+
match self {
659+
Bool(b) => Some(*b),
660+
_ => None,
661+
}
662+
}
655663
fn as_int_range(&self) -> Option<&IntRange> {
656664
match self {
657665
IntRange(range) => Some(range),
@@ -696,10 +704,11 @@ impl<'tcx> Constructor<'tcx> {
696704
_ => bug!("Unexpected type for `Single` constructor: {:?}", pcx.ty),
697705
},
698706
Slice(slice) => slice.arity(),
699-
Str(..)
707+
Bool(..)
708+
| IntRange(..)
700709
| F32Range(..)
701710
| F64Range(..)
702-
| IntRange(..)
711+
| Str(..)
703712
| Opaque
704713
| NonExhaustive
705714
| Hidden
@@ -821,6 +830,7 @@ impl<'tcx> Constructor<'tcx> {
821830

822831
(Single, Single) => true,
823832
(Variant(self_id), Variant(other_id)) => self_id == other_id,
833+
(Bool(self_b), Bool(other_b)) => self_b == other_b,
824834

825835
(IntRange(self_range), IntRange(other_range)) => self_range.is_subrange(other_range),
826836
(F32Range(self_from, self_to, self_end), F32Range(other_from, other_to, other_end)) => {
@@ -873,9 +883,10 @@ pub(super) enum ConstructorSet {
873883
hidden_variants: Vec<VariantIdx>,
874884
non_exhaustive: bool,
875885
},
886+
/// Booleans.
887+
Bool,
876888
/// The type is spanned by integer values. The range or ranges give the set of allowed values.
877889
/// The second range is only useful for `char`.
878-
/// This is reused for bool. FIXME: don't.
879890
/// `non_exhaustive` is used when the range is not allowed to be matched exhaustively (that's
880891
/// for usize/isize).
881892
Integers { range_1: IntRange, range_2: Option<IntRange>, non_exhaustive: bool },
@@ -927,9 +938,7 @@ impl ConstructorSet {
927938
// Invariant: this is `Uninhabited` if and only if the type is uninhabited (as determined by
928939
// `cx.is_uninhabited()`).
929940
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,
933942
ty::Char => {
934943
// The valid Unicode Scalar Value ranges.
935944
Self::Integers {
@@ -1091,6 +1100,19 @@ impl ConstructorSet {
10911100
missing.push(NonExhaustive);
10921101
}
10931102
}
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+
}
10941116
ConstructorSet::Integers { range_1, range_2, non_exhaustive } => {
10951117
let seen_ranges: Vec<_> =
10961118
seen.map(|ctor| ctor.as_int_range().unwrap().clone()).collect();
@@ -1286,10 +1308,11 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
12861308
}
12871309
_ => bug!("bad slice pattern {:?} {:?}", constructor, pcx),
12881310
},
1289-
Str(..)
1311+
Bool(..)
1312+
| IntRange(..)
12901313
| F32Range(..)
12911314
| F64Range(..)
1292-
| IntRange(..)
1315+
| Str(..)
12931316
| Opaque
12941317
| NonExhaustive
12951318
| Hidden
@@ -1430,7 +1453,14 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
14301453
}
14311454
PatKind::Constant { value } => {
14321455
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(_) => {
14341464
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
14351465
Some(bits) => IntRange(IntRange::from_bits(cx.tcx, pat.ty, bits)),
14361466
None => Opaque,
@@ -1605,8 +1635,9 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
16051635
}
16061636
}
16071637
}
1608-
&Str(value) => PatKind::Constant { value },
1638+
Bool(b) => PatKind::Constant { value: mir::Const::from_bool(cx.tcx, *b) },
16091639
IntRange(range) => return range.to_pat(cx.tcx, self.ty),
1640+
&Str(value) => PatKind::Constant { value },
16101641
Wildcard | NonExhaustive | Hidden => PatKind::Wild,
16111642
Missing { .. } => bug!(
16121643
"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> {
17871818
}
17881819
write!(f, "]")
17891820
}
1821+
Bool(b) => write!(f, "{b}"),
1822+
// Best-effort, will render signed ranges incorrectly
1823+
IntRange(range) => write!(f, "{range:?}"),
17901824
F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"),
17911825
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`
17931826
Str(value) => write!(f, "{value}"),
17941827
Opaque => write!(f, "<constant pattern>"),
17951828
Or => {

0 commit comments

Comments
 (0)