Description
Seems to be a reroll #20678. I have some idea how to fix it, will try to draft a pull request later, but it basically requires checking the sign of the i64
, neg
ging if required and casting to u64
, and using checked_add
or checked_sub
.
I will divide into cases to demonstrate that this is required, to save repeating phrases, I will use the following notation:
S means pos < i64::max_value()
, L means pos > i64::max_value()
;
P means n >= 0
, N means n < 0
;
O+ means we will notice bads by checking OF on add (u64::checked_add
), O- means we will notice them by checking OF on sub (u64::checked_sub
after i64::wrapping_neg
), Z+ means we will notice by adding as i64
and making sure result is non-negative, Z- is making sure it is negative, D+ mean we will notice bads by asserting OF is set on add (u64::overflowing_add
), D- is likewise for sub (u64::overflowing_sub
). Note the we don't need to consider n == i64::min_value()
, because after i64::wrapping_neg
and as u64
we still get the right, large, positive number.
So, we have the following cases and appropriate checks that spot trouble:
- SP -> O+Z+D- (there's never a problem, but the others false-positive)
- LP -> O+Z-D- (but D- requires also that the result is non-zero).
- SN -> O-Z+D+
- LN -> O-D+ (there's never a problem, but the others false-positive)
Overall, we see that there is no one test which works for all cases, and a minimum of two cases (and tests) yields the solution described above.