-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
std::i32::MIN.abs() results in panicked at 'arithmetic operation overflowed' #25378
Comments
I believe that the documentation has not been updated since the new overflow semantics landed, and this is otherwise correctly panicking on overflow for debug builds. I'm going to tag this as A-docs as it sounds like we need to update the docs. Thanks for the report! |
Fair enough. So this is intentional. Sadly, I am now 0-for-2 on new issue reports today. I guess I don't understand rust as well as I thought yet :-( Thanks for the clarification in both cases, and sorry for the extra noise on the issues list. I agree a document update would be helpful, possibly even mentioning that that abs(Int::min_value()) will produce an arithmetic overflow panick. Thanks and keep up the good work! |
See also rust-lang/rfcs#1017 for a very relevant discussion / potential API addition. |
Thanks! Very enlightening points of view. This is a sticky issue indeed. If you will allow me to add my 2 cents as a newbie and potential adopter of Rust in "real life" in the near future.
abs :: a -> a |
OK... I should have looked at So this may not be a documentation issue with 1.0.0-beta.5 after all, but rather something that was changed/fixed subsequently in the master and not back-ported to 1.0.0-beta.5. The proposed change to Here is the code from libcore/num/mod.rs:570 pub fn abs(self) -> $T {
if self.is_negative() {
self.wrapping_neg()
} else {
self
}
} libcore/num/mod.rs:1068 pub fn wrapping_neg(self) -> $T {
self.overflowing_neg().0
} libcore/num/wrapping.rs:231 fn overflowing_neg(self) -> ($t, bool) {
if self == $t::MIN {
($t::MIN, true)
} else {
(-self, false)
}
} What do you think? Am I headed down the right path with my investigation here, or just wasting my time? Will post my results after I finish my testing with nightly later this evening. |
@econoplas I strongly recommend using beta was deliberately switched from using I think there was probably a mistake somewhere here, but switching it back to History I'm referencing:
|
@pnkfelix the Overall it sounds like the behavior on nightly is as intended (using wrapping semantics and not panicking), and the behavior on beta is a mistake because it's using Sorry for giving you the runaround @econoplas! |
Not a problem. Thanks for looking into this and listening to my noobie feedback! And for not laughing at my ignorance :-) Confirmed that the code from my original post above works with no panic with 1.1.0-dev nightly 20150513. I am OK with closing this without resolving the strange But I should mention what started me down this path to begin with was my 1.0.0-beta.5 build crashed in But that also led me to investigate why My concern is that if Knowing what I know now about the issue submittal process, I wish I would have kept the stack trace from my failed 1.0.0-beta.5 compile on CentOS 6.5. I will try to reproduce the build crashing in Thanks again! |
Debug overflow checks for arithmetic negation landed in rust-lang#24500, at which time the `abs` method on signed integers was changed to using `wrapping_neg` to ensure that the function never panicked. This implied that `abs` of `INT_MIN` would return `INT_MIN`, another negative value. When this change was back-ported to beta, however, in rust-lang#24708, the `wrapping_neg` function had not yet been backported, so the implementation was changed in rust-lang#24785 to `!self + 1`. This change had the unintended side effect of enabling debug overflow checks for the `abs` function. Consequently, the current state of affairs is that the beta branch checks for overflow in debug mode for `abs` and the nightly branch does not. This commit alters the behavior of nightly to have `abs` always check for overflow in debug mode. This change is more consistent with the way the standard library treats overflow as well, and it is also not a breaking change as it's what the beta branch currently does (albeit if by accident). cc rust-lang#25378
@econoplas we actually discussed this a bit more at triage yesterday and the conclusion was that we may actually want |
Thanks for the update! I tracked down the place in the 1.0.0 code where i32::MIN::abs() was causing compilation from source to panic compiling stage1 libcore, and verified it still occurs with the 1.0.0 release. See #25492 which includes my analysis as well as a patch. I also spent a couple of hours searching for all possible calls to MIN::abs() and reading those sections of code, and this was the only place I could find where MIN::abs() is explicitly called. The thought being that if MIN::abs() in 1.0.0 is still vulnerable to panic behaviour, then someone should look at all calls to abs() in the code base to see if any obvious panics will occur. Hopefully I didn't miss any :-) |
Debug overflow checks for arithmetic negation landed in rust-lang#24500, at which time the `abs` method on signed integers was changed to using `wrapping_neg` to ensure that the function never panicked. This implied that `abs` of `INT_MIN` would return `INT_MIN`, another negative value. When this change was back-ported to beta, however, in rust-lang#24708, the `wrapping_neg` function had not yet been backported, so the implementation was changed in rust-lang#24785 to `!self + 1`. This change had the unintended side effect of enabling debug overflow checks for the `abs` function. Consequently, the current state of affairs is that the beta branch checks for overflow in debug mode for `abs` and the nightly branch does not. This commit alters the behavior of nightly to have `abs` always check for overflow in debug mode. This change is more consistent with the way the standard library treats overflow as well, and it is also not a breaking change as it's what the beta branch currently does (albeit if by accident). cc rust-lang#25378
Debug overflow checks for arithmetic negation landed in #24500, at which time the `abs` method on signed integers was changed to using `wrapping_neg` to ensure that the function never panicked. This implied that `abs` of `INT_MIN` would return `INT_MIN`, another negative value. When this change was back-ported to beta, however, in #24708, the `wrapping_neg` function had not yet been backported, so the implementation was changed in #24785 to `!self + 1`. This change had the unintended side effect of enabling debug overflow checks for the `abs` function. Consequently, the current state of affairs is that the beta branch checks for overflow in debug mode for `abs` and the nightly branch does not. This commit alters the behavior of nightly to have `abs` always check for overflow in debug mode. This change is more consistent with the way the standard library treats overflow as well, and it is also not a breaking change as it's what the beta branch currently does (albeit if by accident). cc #25378
Debug overflow checks for arithmetic negation landed in rust-lang#24500, at which time the `abs` method on signed integers was changed to using `wrapping_neg` to ensure that the function never panicked. This implied that `abs` of `INT_MIN` would return `INT_MIN`, another negative value. When this change was back-ported to beta, however, in rust-lang#24708, the `wrapping_neg` function had not yet been backported, so the implementation was changed in rust-lang#24785 to `!self + 1`. This change had the unintended side effect of enabling debug overflow checks for the `abs` function. Consequently, the current state of affairs is that the beta branch checks for overflow in debug mode for `abs` and the nightly branch does not. This commit alters the behavior of nightly to have `abs` always check for overflow in debug mode. This change is more consistent with the way the standard library treats overflow as well, and it is also not a breaking change as it's what the beta branch currently does (albeit if by accident). cc rust-lang#25378
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 theif
condition for the block that returns "!self + 1" inabs
implementation such as:I tried this code:
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
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:
Output:
The text was updated successfully, but these errors were encountered: