216. unsigned_abs — i32::MIN Has No Positive Twin, So .abs() Overflows
(-5i32).abs() is fine, but i32::MIN.abs() panics — the magnitude 2147483648 doesn’t fit back into an i32. unsigned_abs returns the magnitude in the unsigned type, where it always fits.
Two’s complement isn’t symmetric. An i32 reaches down to -2147483648 but only up to 2147483647, so the most-negative value has no positive counterpart. That makes abs a landmine on exactly one input:
| |
The same trap hides inside the classic (a - b).abs() distance trick, which is why abs_diff exists for differences. But when you have a single signed value and just want its magnitude, the fix is unsigned_abs:
| |
It returns the unsigned sibling type (i32 → u32, i8 → u8, …), which is wide enough to hold the magnitude of every input — including the awkward one — so it can never overflow:
| |
If you genuinely need a signed result and want to handle the edge instead of ignoring it, checked_abs hands you an Option and saturating_abs clamps to MAX:
| |
Any time you take the absolute value of a signed integer that could conceivably be MIN — parsed input, a subtraction result, a delta from untrusted data — reach for unsigned_abs instead of abs and the panic simply can’t happen.