I had to do ASCII to i32 parsing on an embedded target, and I build up the value in a u32 which has enough range to cover 0..i32::MAX+1.
However, when I try to stuff that back into an i32, the simple "-(value as i32)" works EXCEPT if the value is i32::MAX+1 which is a valid negative number (abs(i32::MIN) == abs(i32::MAX+1)).
What silly stupid thing am I missing to do this negation? Do I really have to cast to an i64 just to negate this because of one single value? That seems very silly.
Thanks.
fn main() {
let a: u32 = i32::MAX as u32;
let b: u32 = a + 1;
println!("a:{} b:{}", a, b);
let c: i32 = -(a as i32);
println!("c: {}", c);
let d: i32 = -(b as i32);
println!("d: {}", d);
println!("OK");
}
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized + debuginfo] target(s) in 3.38s
Running `target/debug/playground`
thread 'main' panicked at 'attempt to negate with overflow', src/main.rs:13:18
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Unfortunately yes, because Rust panics on integer overflow. This was precisely the issue pointed out by Linus Torvalds when he was considering making Rust a language parts of the Linux kernel could be written in.
fn main()
{
let a: u32 = i32::MAX as u32;
let b: u32 = a + 1;
println!("{}", a as i32);
println!("{}", b as i32);
println!("{}", (a as i32).wrapping_neg());
println!("{}", (b as i32).wrapping_neg());
}