mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-02 19:53:46 +00:00
Auto merge of #57978 - varkor:fix-irrefutable-integer-range-match, r=oli-obk
Fix bug in integer range matching Fixes #57894.
This commit is contained in:
commit
852701ad6d
@ -106,27 +106,34 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PatternKind::Range(PatternRange { lo, hi, ty, end }) => {
|
PatternKind::Range(PatternRange { lo, hi, ty, end }) => {
|
||||||
let range = match ty.sty {
|
let (range, bias) = match ty.sty {
|
||||||
ty::Char => {
|
ty::Char => {
|
||||||
Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32)))
|
(Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))), 0)
|
||||||
}
|
}
|
||||||
ty::Int(ity) => {
|
ty::Int(ity) => {
|
||||||
// FIXME(49937): refactor these bit manipulations into interpret.
|
// FIXME(49937): refactor these bit manipulations into interpret.
|
||||||
let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
|
let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
|
||||||
let min = 1u128 << (size.bits() - 1);
|
let max = !0u128 >> (128 - size.bits());
|
||||||
let max = (1u128 << (size.bits() - 1)) - 1;
|
let bias = 1u128 << (size.bits() - 1);
|
||||||
Some((min, max, size))
|
(Some((0, max, size)), bias)
|
||||||
}
|
}
|
||||||
ty::Uint(uty) => {
|
ty::Uint(uty) => {
|
||||||
// FIXME(49937): refactor these bit manipulations into interpret.
|
// FIXME(49937): refactor these bit manipulations into interpret.
|
||||||
let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size();
|
let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size();
|
||||||
let max = !0u128 >> (128 - size.bits());
|
let max = !0u128 >> (128 - size.bits());
|
||||||
Some((0, max, size))
|
(Some((0, max, size)), 0)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => (None, 0),
|
||||||
};
|
};
|
||||||
if let Some((min, max, sz)) = range {
|
if let Some((min, max, sz)) = range {
|
||||||
if let (Some(lo), Some(hi)) = (lo.val.try_to_bits(sz), hi.val.try_to_bits(sz)) {
|
if let (Some(lo), Some(hi)) = (lo.val.try_to_bits(sz), hi.val.try_to_bits(sz)) {
|
||||||
|
// We want to compare ranges numerically, but the order of the bitwise
|
||||||
|
// representation of signed integers does not match their numeric order.
|
||||||
|
// Thus, to correct the ordering, we need to shift the range of signed
|
||||||
|
// integers to correct the comparison. This is achieved by XORing with a
|
||||||
|
// bias (see pattern/_match.rs for another pertinent example of this
|
||||||
|
// pattern).
|
||||||
|
let (lo, hi) = (lo ^ bias, hi ^ bias);
|
||||||
if lo <= min && (hi > max || hi == max && end == RangeEnd::Included) {
|
if lo <= min && (hi > max || hi == max && end == RangeEnd::Included) {
|
||||||
// Irrefutable pattern match.
|
// Irrefutable pattern match.
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
7
src/test/ui/match-on-negative-integer-ranges.rs
Normal file
7
src/test/ui/match-on-negative-integer-ranges.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// run-pass
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(false, match -50_i8 { -128i8..=-101i8 => true, _ => false, });
|
||||||
|
|
||||||
|
assert_eq!(false, if let -128i8..=-101i8 = -50_i8 { true } else { false });
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user