Skip to content

Make Signed::abs match its documented behavior for ::MIN - #380

Open
tautschnig wants to merge 2 commits into
rust-num:mainfrom
tautschnig:fix-abs-min-overflow
Open

Make Signed::abs match its documented behavior for ::MIN#380
tautschnig wants to merge 2 commits into
rust-num:mainfrom
tautschnig:fix-abs-min-overflow

Conversation

@tautschnig

Copy link
Copy Markdown

The Signed trait documentation states: "For signed integers, ::MIN will be returned if the number is ::MIN." The primitive implementations use unary negation, which panics with "attempt to negate with overflow" when overflow checks are enabled (debug builds):

let r = num_traits::abs(i32::MIN); // debug: panic; release: returns i32::MIN as documented

This PR switches the implementation to wrapping_abs, which implements the documented semantics in both build profiles, and adds a regression test (which runs with overflow checks enabled by default, so it would panic without the fix).

It also documents the overflow behavior of abs_sub for signed integers (e.g. i32::MAX.abs_sub(&-1) is not representable), which panics with overflow checks enabled and wraps otherwise; changing that behavior (e.g. saturating) seemed like a semantic decision better left to the maintainers, so this PR only documents it.

Found by running Kani's autoharness (model-checking/kani#3832) over the crate: the generated harness for abs::<i32> reported the negate-overflow panic reachable; reproduced with plain cargo (no Kani involved) before filing.

The trait documentation states: "For signed integers, ::MIN will be
returned if the number is ::MIN." The implementation used unary negation,
which panics with 'attempt to negate with overflow' when overflow checks
are enabled (debug builds), so the documented behavior only held in release
builds. Use wrapping_abs, which implements the documented semantics in both
profiles.

Also document the overflow behavior of abs_sub for signed integers (e.g.
MAX.abs_sub(&-1) is not representable): it panics with overflow checks
enabled and wraps otherwise.

Found by running Kani's autoharness (model-checking/kani#3832) over
num-traits: the generated harness for abs::<i32> reported the negate
overflow reachable at sign.rs.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 3, 2026 11:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates Signed::abs for primitive signed integers to match the trait’s documented ::MIN behavior in debug (overflow-checking) builds, and adds a regression test to prevent reintroducing the overflow panic.

Changes:

  • Switch primitive signed integer Signed::abs implementation from negation to wrapping_abs to avoid ::MIN negate overflow panics.
  • Add a regression test ensuring abs(::MIN) == ::MIN across signed integer primitives and the sign::abs helper.
  • Document the overflow behavior of Signed::abs_sub for signed integers when the difference is not representable.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/sign.rs Outdated
Comment on lines +21 to +23
/// For signed integers, the difference may not be representable (e.g.
/// `MAX.abs_sub(&-1)`), in which case the subtraction overflows: it panics when overflow
/// checks are enabled and wraps around otherwise.
Review feedback: MAX.abs_sub(&-1) is ambiguous without a concrete integer
type; use i32::MAX so the example can be read (and copied) unmodified.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants