Skip to content

std::i32::MIN.abs() results in panicked at 'arithmetic operation overflowed' #25378

@econoplas

Description

@econoplas

I encountered 'arithmetic operation overflowed' panick when calling std::i32::MIN.abs() and similarly for i8, i16, and i64.

The docs for 1.0.0-beta.5 std::num abs function says:

Int::min_value() will be returned if the number is Int::min_value().

I suspect && self != <$T>::min_value() is needed in the if condition for the block that returns "!self + 1" inabs implementation such as:

        pub fn abs(self) -> $T {
            if self.is_negative() && self != $T::min_value() {
                !self + 1 // wrapping_neg
            } else {
                self
            }
        }

I tried this code:

fn main() {
    println!("{}", (std::i8::MIN).abs());   // Expected i8::MIN
    println!("{}", (std::i16::MIN).abs());  // Expected i16::MIN
    println!("{}", (std::i32::MIN).abs());  // Expected i32::MIN
    println!("{}", (std::i64::MIN).abs());  // Expected i64::MIN
}

I expected to see this happen:
-128
-32768
-2147483648
-9223372036854775808

Instead, this happened:
thread '<main>' panicked at 'arithmetic operation overflowed', /tmp/build/rustc-1.0.0-beta.5/src/libcore/num/mod.rs:509

Meta

rustc --version --verbose:
rustc 1.0.0-dev (built 2015-05-13)
binary: rustc
commit-hash: unknown
commit-date: unknown
build-date: 2015-05-13
host: x86_64-unknown-linux-gnu
release: 1.0.0-dev

$ RUST_BACKTRACE=1 ./try_abs2

thread '<main>' panicked at 'arithmetic operation overflowed', /tmp/build/rustc-1.0.0-beta.5/src/libcore/num/mod.rs:509
stack backtrace:
   1:     0x7f181b0a98f9 - sys::backtrace::write::he573c8167e01081cd4r
   2:     0x7f181b0acab8 - panicking::on_panic::had2e9609e9ec19cdjrw
   3:     0x7f181b0a5f32 - rt::unwind::begin_unwind_inner::h2b37885f8310bdebt6v
   4:     0x7f181b0a61ec - rt::unwind::begin_unwind_fmt::h8504c97e3506491474v
   5:     0x7f181b0ac426 - rust_begin_unwind
   6:     0x7f181b0d5094 - panicking::panic_fmt::hdf7ef67474c35dd3wwy
   7:     0x7f181b0d5014 - panicking::panic::hf43ff458bd7d8b953uy
   8:     0x7f181b0a470d - num::i8::abs::h3652d8ae9a3c4a64Qhc
   9:     0x7f181b0a432b - main::h50fc8aac82f30ec4eaa
  10:     0x7f181b0b0a48 - rust_try_inner
  11:     0x7f181b0b0a35 - rust_try
  12:     0x7f181b0ae20b - rt::lang_start::hed504002616c7361Olw
  13:     0x7f181b0a4b7e - main
  14:     0x7f181a29daf4 - __libc_start_main
  15:     0x7f181b0a41d8 - <unknown>
  16:                0x0 - <unknown>

As a side-node, I tried this with C (gcc 4.8.3) on the same platform (CentOS 7 x86_64) and abs(INT_MIN) returns INT_MIN, and labs(LONG_MIN) returns LONG_MIN in case there is question whether Rust's documented behavior of abs() returning Int::min_value() is consistent with common C/C++ library implementation (and it is).

Disclaimer: This is C code:

   printf("%d %d\n", INT_MIN, abs(INT_MIN));
   printf("%ld %ld\n", LONG_MIN, labs(LONG_MIN));

Output:

    -2147483648 -2147483648
    -9223372036854775808 -9223372036854775808

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions