Skip to content

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

Closed
@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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions