Skip to content

Decouple operator supertraits from arithmetic traits (0.2.0) - #14

Merged
kaidokert merged 2 commits into
mainfrom
feat/op-supertrait-output-decoupling
Jul 10, 2026
Merged

kaidokert merged 2 commits into
mainfrom
feat/op-supertrait-output-decoupling

Conversation

@kaidokert

@kaidokert kaidokert commented Jul 9, 2026

Copy link
Copy Markdown
Owner

Breaking (0.2.0). Removes the core::ops operator supertrait that the arithmetic traits carried solely to source their return type, replacing the projection with a fresh trait-local type Output.

Why

WrappingAdd: Add<Self> returning <Self as Add<Self>>::Output leaked an Add<Output = Self> requirement onto every consumer, and forced a backend to implement the operator just to implement the wrapping trait — even though wrapping_add is a distinct operation from + (a backend whose + panics still has a well-defined wrapping_add). Each such trait now carries its own type Output and drops the operator supertrait.

  • Consumers bound WrappingAdd<Output = Self> (the trait they use), not WrappingAdd + Add<Output = Self> (the operator they don't).
  • Non-Copy backends keep the impl Trait for &T owned-return path — that is the reason for an associated Output rather than a bare -> Self. This was the hard requirement driving the design.
  • Primitive impls are unchanged (their Output is Self); PrimInt's CheckedAdd<Output = Self> bounds and the Wrapping<T> blanket impls keep resolving.

Scope (from a 4-way audit of the whole trait surface)

  • 51 traits across checked/wrapping/saturating/overflowing/strict/rounding(DivCeil/DivFloor)/carrying(CarryingAdd/BorrowingSub)/bits(UnboundedShl/Shr, ShlExact/ShrExact) → fresh type Output.
  • Euclid → single type Output (div and rem share it); Checked/Wrapping/Overflowing/StrictEuclid re-spell through <Self as Euclid>::Output.
  • CarryingMul → second assoc type for the high word (alongside type Unsigned).
  • Pure-leak supertrait drops: WideningMul's dead Mul (returns via type Wide); the Rem on MultipleOf/DivExact/NextMultipleOf that never sourced a return.
  • Sign traits relaxed: Signed: NumZero + PartialOrd + Neg + Signum; Unsigned: bare marker — so sign queries don't drag in Div/Rem/One (a CT/non-divisible signed type can now answer is_positive/abs).

Migration

Replace T: WrappingAdd + Add<Output = T>-style bounds with T: WrappingAdd<Output = T>, and drop operator bounds that were only present to pin the projection. Impl sites are unchanged.

Verified: stable (lib + integration + 259 doctests), nightly --features nightly,ct (const surface + 261 doctests), clippy clean on default + ct, and the no_std / ct / libm build configs.

Summary by CodeRabbit

  • New Features

    • Expanded numeric operation support with more consistent result typing across checked, overflowing, saturating, wrapping, and Euclidean operations.
    • Improved compatibility for custom numeric types by reducing reliance on standard operator traits.
  • Bug Fixes

    • Simplified signed/unsigned handling and power calculations to work with narrower capability requirements.
    • Updated public arithmetic APIs to return clearer, more predictable output types.
  • Chores

    • Bumped the package version to 0.2.0.

…utput (0.2.0)

The checked/wrapping/saturating/overflowing/strict/euclid/rounding/carrying
traits routed their return type through a core::ops operator supertrait
(WrappingAdd: Add<Self>, returning <Self as Add<Self>>::Output). That leaked an
Add<Output=Self> requirement onto every consumer and forced backends to impl the
operator just to impl the wrapping trait — even though wrapping_add is a distinct
operation from +. Each such trait now carries its own fresh 'type Output' and
drops the operator supertrait, so consumers bound on WrappingAdd<Output=Self>
(the trait they use) rather than the operator they don't. Non-Copy backends keep
the impl-for-&T owned-return path (the reason for an associated Output rather
than a bare -> Self).

Also, dropping pure-leak supertraits surfaced by the same audit: WideningMul's
dead Mul<Self> (returns via type Wide); the Rem<Self> on MultipleOf/DivExact/
NextMultipleOf that never sourced a return; and relaxing Signed (Num ->
Zero + PartialOrd + Neg + Signum) and Unsigned (bare marker) so sign queries
don't drag in Div/Rem/One. Euclid gains a single type Output (div and rem share
it); its Checked/Wrapping/Overflowing/Strict variants re-spell through it.
CarryingMul gains a second assoc type for the high word.

Consumers: replace 'T: WrappingAdd + Add<Output=T>' style bounds with
'T: WrappingAdd<Output=T>'; drop operator bounds only present for the projection.
Impls are unchanged (primitive Output is Self). Breaking; targets 0.2.0.

@sourcery-ai sourcery-ai Bot 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.

Sorry @kaidokert, you have reached your weekly rate limit of 1500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 37 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c0913198-c10d-4f01-95ec-855fb737935a

📥 Commits

Reviewing files that changed from the base of the PR and between a20b1a3 and 7244c68.

📒 Files selected for processing (2)
  • README.md
  • src/int.rs
📝 Walkthrough

Walkthrough

This PR refactors numeric operation traits (bits, carrying, checked, euclid, overflowing, rounding, saturating, strict, wrapping) to use explicit associated Output types instead of deriving return types from core::ops operator trait bounds. Signed/Unsigned bounds shift from Num to Zero/PartialOrd. Version bumped to 0.2.0.

Changes

Associated Output type refactor

Layer / File(s) Summary
Bit shift traits
src/ops/bits.rs
UnboundedShl/UnboundedShr and ShlExact/ShrExact gain associated Output types, dropping Shl<u32>/Shr<u32> bounds; primitive impls set Output.
Carrying/borrowing/widening multiplication
src/ops/carrying.rs
CarryingAdd, BorrowingSub, CarryingMul, WideningMul drop Add/Sub/Mul bounds and add Output (and Unsigned for CarryingMul); macro and 128-bit impls updated; unused import removed.
Checked arithmetic
src/ops/checked.rs
CheckedAdd/Sub/Mul/Div/Rem/Shl/Shr/Abs/Pow add Output and update return signatures; test helpers use Output-based bounds.
Euclid and dependents
src/ops/euclid.rs
Euclid gains Output; CheckedEuclid, WrappingEuclid, OverflowingEuclid reference Euclid::Output; float impls set Output explicitly.
Overflowing arithmetic
src/ops/overflowing.rs
OverflowingAdd/Sub/Mul/Div/Rem/Neg/Abs/Shl/Shr/Pow add Output and drop operator supertraits; macro impls updated.
Rounding and multiple-of
src/ops/rounding.rs
DivCeil, DivFloor, DivExact, MultipleOf, NextMultipleOf drop operator bounds and add Output; impl macros updated; unused import removed.
Saturating arithmetic
src/ops/saturating.rs
Deprecated Saturating and SaturatingAdd/Sub/Mul/Div/Neg/Abs/Pow add Output; macro impls updated.
Strict arithmetic
src/ops/strict.rs
StrictAdd/Sub/Mul/Div/Rem/Abs/Shl/Shr/Pow add Output; StrictEuclid uses Euclid::Output.
Wrapping arithmetic and blanket impls
src/ops/wrapping.rs
WrappingAdd/Sub/Mul/Neg/Shl/Shr/Div/Rem/Abs/Pow add Output; Wrapping<T> blanket impls switch to Output-based bounds.
Downstream usages
src/pow.rs, src/sign.rs
checked_pow relies on CheckedMul<Output = T>; Signed/Unsigned drop Num in favor of Zero/PartialOrd; Wrapping<T> blanket impls adjusted.
Version bump
Cargo.toml
Package version updated from 0.1.2 to 0.2.0.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • kaidokert/num-traits#7: Continues the same const-trait refactor of src/ops/* arithmetic trait APIs, adding associated Output types and changing return types across the same modules.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: removing operator supertraits from arithmetic traits, and the version bump is also accurate.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/op-supertrait-output-decoupling

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request decouples various mathematical and bitwise operation traits from standard library operator traits (such as Add, Sub, Mul, Div, Rem, Shl, Shr, and Neg) by removing them as supertraits and introducing an associated Output type. This change allows for more flexible implementations, particularly for non-Copy types, and simplifies blanket implementations for Wrapping. Additionally, the Signed and Unsigned traits have had their bounds relaxed (e.g., replacing Num with Zero + PartialOrd or Sized). There are no review comments, so I have no further feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a20b1a3f82

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/ops/saturating.rs

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
Cargo.toml (1)

11-11: 📐 Maintainability & Code Quality | 🔵 Trivial

Keep the published version and README examples in sync.

README.md still tells consumers to depend on 0.1, so shipping 0.2.0 without updating those examples will point users at the wrong upgrade path. Please update the dependency snippets alongside this bump.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Cargo.toml` at line 11, The published version in Cargo.toml has been bumped
to 0.2.0, but the README dependency examples still reference 0.1, so update the
README snippets to match the new release. Keep the version string in sync across
the package metadata and the example dependency declarations so consumers are
pointed to the correct upgrade path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@Cargo.toml`:
- Line 11: The published version in Cargo.toml has been bumped to 0.2.0, but the
README dependency examples still reference 0.1, so update the README snippets to
match the new release. Keep the version string in sync across the package
metadata and the example dependency declarations so consumers are pointed to the
correct upgrade path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9a15dd14-d45d-464d-afd5-08309197fee8

📥 Commits

Reviewing files that changed from the base of the PR and between ca16b36 and a20b1a3.

📒 Files selected for processing (12)
  • Cargo.toml
  • src/ops/bits.rs
  • src/ops/carrying.rs
  • src/ops/checked.rs
  • src/ops/euclid.rs
  • src/ops/overflowing.rs
  • src/ops/rounding.rs
  • src/ops/saturating.rs
  • src/ops/strict.rs
  • src/ops/wrapping.rs
  • src/pow.rs
  • src/sign.rs

PrimInt inherits Saturating unpinned, so after Saturating gained a type Output,
generic PrimInt code saw saturating_add return an opaque <T as Saturating>::Output
instead of Self. Pin it like the CheckedAdd/Sub/Mul/Div supertraits already are.
Also sync the README dependency snippets to 0.2.
@kaidokert
kaidokert merged commit f00417d into main Jul 10, 2026
9 checks passed
@kaidokert
kaidokert deleted the feat/op-supertrait-output-decoupling branch July 11, 2026 05:22
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.

1 participant