Skip to content

Commit 5f52fa7

Browse files
committed
🎨 Improve code clarity
1 parent 425ea9c commit 5f52fa7

File tree

1 file changed

+43
-26
lines changed

1 file changed

+43
-26
lines changed

compiler-core/src/exhaustiveness.rs

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3598,19 +3598,17 @@ fn int_to_bits(
35983598
let mut bytes = int_to_bytes(value, endianness, signed);
35993599
let bytes_size = bytes.len() * 8;
36003600

3601-
// There are 3 cases, which are easier to handle separately by endianness
3602-
// If the size of the bigint bytes equals the expected bits, we can return them as-is
3603-
// If there are more bits than we need, we need to trim some of the most significant bits.
3604-
// E.g. `6:3` yields one byte of which we need to trim the 5 most significant bits.
3605-
// Values like 999:3 are illegal and caught by the guard at the start of the function.
3606-
// If there are fewer bits than we need, we need to add some.
3607-
// E.g. `6:13` yields one byte which we need to pad with 5 bits
36083601
let bits = match (endianness, bytes_size.cmp(&size)) {
36093602
(_, Ordering::Equal) => BitVec::from_vec(bytes),
36103603

3604+
// Even though we return an error if `value` cannot be represented in `size` bits,
3605+
// we may need to slice off up a couple bits if the read size is not a multiple of 8.
3606+
// <3:4> yields the bytes [0b0000_0011]. We slice off 4 bits and get 0011
36113607
(Endianness::Big, Ordering::Greater) => {
36123608
BitVec::from_bitslice(&bytes.view_bits()[bytes_size - size..])
36133609
}
3610+
// If the number needs fewer bits than the read size, we pad it.
3611+
// <3:9> yields the bytes [0b0000_0011]. We add one digit and get 0_0000_0011
36143612
(Endianness::Big, Ordering::Less) => {
36153613
let mut bits = BitVec::repeat(pad_digit, size - bytes_size);
36163614
bits.extend_from_raw_slice(&bytes);
@@ -3782,29 +3780,36 @@ fn representable_with_bits(value: &BigInt, bits: u32, signed: bool) -> bool {
37823780
if bits == 0 {
37833781
return false;
37843782
};
3785-
let is_negative = value.sign() == Sign::Minus;
3786-
if is_negative && !signed {
3787-
return false;
3788-
}
37893783

3790-
let bits_unsigned = value.bits();
3791-
let required_bits = if !signed {
3792-
bits_unsigned
3793-
} else if !is_negative {
3794-
// The minimal representation of an unsigned number always has 1 as its most
3795-
// significant bit and thus always needs an extra bit for the sign.
3796-
bits_unsigned + 1
3797-
} else if let Some(trailing_zeros) = value.trailing_zeros() {
3798-
// Negative powers of two don't need an extra sign bit. E.g. `-2 == 0b10`
3799-
let is_power_of_2 = trailing_zeros == bits_unsigned - 1;
3800-
bits_unsigned + (!is_power_of_2 as u64)
3801-
} else {
3802-
// The value is 0
3803-
1
3784+
let required_bits = match (value.sign(), signed) {
3785+
// Zero always needs one bit.
3786+
(Sign::NoSign, _) => 1,
3787+
3788+
// `BigInt::bits` does not consider the sign!
3789+
(Sign::Plus, false) => value.bits(),
3790+
// Therefore we need to add the sign bit here: `10` -> `010`
3791+
(Sign::Plus, true) => value.bits() + 1,
3792+
3793+
// A negative number must be signed
3794+
(Sign::Minus, false) => return false,
3795+
(Sign::Minus, true) => {
3796+
let bits_unsigned = value.bits();
3797+
let trailing_zeros = value
3798+
.trailing_zeros()
3799+
.expect("trailing_zeros to return a value for non-zero numbers");
3800+
let is_power_of_2 = trailing_zeros == bits_unsigned - 1;
3801+
3802+
// Negative powers of two don't need an extra sign bit. E.g. `-2 == 0b10`
3803+
if is_power_of_2 {
3804+
bits_unsigned
3805+
} else {
3806+
bits_unsigned + 1
3807+
}
3808+
}
38043809
};
38053810

38063811
match required_bits.to_u32() {
3807-
Some(r) => bits >= r,
3812+
Some(required_bits) => bits >= required_bits,
38083813
None => false,
38093814
}
38103815
}
@@ -3846,6 +3851,18 @@ mod representable_with_bits_test {
38463851
assert!(!representable_with_bits(&BigInt::from(-9), 3, true));
38473852
}
38483853

3854+
#[test]
3855+
fn zero_representable_with_bits_test() {
3856+
for i in 0..12 {
3857+
println!("{i}: {}", BigInt::from(i).bits());
3858+
}
3859+
assert!(!representable_with_bits(&BigInt::ZERO, 0, false));
3860+
assert!(!representable_with_bits(&BigInt::ZERO, 0, true));
3861+
3862+
assert!(representable_with_bits(&BigInt::ZERO, 1, false));
3863+
assert!(representable_with_bits(&BigInt::ZERO, 1, true));
3864+
}
3865+
38493866
#[test]
38503867
fn number_representable_with_sign_test() {
38513868
// Sign needs one additional bit

0 commit comments

Comments
 (0)