Skip to content

Add documentation note about signed overflow direction#152179

Merged
rust-bors[bot] merged 1 commit intorust-lang:mainfrom
nickkuk:overflow-direction-note
Feb 18, 2026
Merged

Add documentation note about signed overflow direction#152179
rust-bors[bot] merged 1 commit intorust-lang:mainfrom
nickkuk:overflow-direction-note

Conversation

@nickkuk
Copy link
Contributor

@nickkuk nickkuk commented Feb 5, 2026

In #151989 (comment) I noticed that signed overflow direction can be determined by returned wrapped value. It is not very obvious (especially, assuming additional carry: bool summand), but it is important if we want to add new leading (signed) limb to big integer in this case.

Examples for small summands x, y: i8 with result extension:

x y overflow result as (u8, i8)
-1 -128 true (127, -1)
0 -1 false (255, -1)
2 2 false (4, 0)
127 1 true (128, 0)

Here is general proof.

  1. Set $s=2^{N-1}$ and let's say iN::carrying_add(x, y, c) returns (result, true) then

$$ \mathrm{result}=\begin{cases} x + y + c + 2s,& x + y + c \le -s-1,\\ x+y+c-2s,& x+y+c\ge s. \end{cases} $$

First case is overflowing below iN::MIN and we have

$$ \mathrm{result}\ge -s-s+0+2s =0;\qquad \mathrm{result}=x + y + c + 2s\le -s-1+2s = s - 1, $$

so we obtain $[0; s-1]$ which is exactly range of non-negative iN.

Second case is overflowing above iN::MAX and

$$ \mathrm{result}=x+y+c-2s\ge s-2s =-s;\qquad \mathrm{result}\le s-1 + s-1+1-2s = -1, $$

that is, $[-s,-1]$ which is exactly range of negative iN.

  1. Now suppose that iN::borrowing_sub(x,y,b) returns (result, true) then

$$ \mathrm{result}=\begin{cases} x - y - b + 2s,& x - y - b \le -s-1,\\ x - y - b - 2s,& x - y - b\ge s. \end{cases} $$

First case is overflowing below iN::MIN and we have

$$ \mathrm{result}\ge -s-(s-1)-1+2s =0;\qquad \mathrm{result}=x - y - b + 2s\le -s-1+2s = s - 1. $$

Second case is overflowing above iN::MAX and

$$ \mathrm{result}=x-y-b-2s\ge s-2s =-s;\qquad \mathrm{result}\le s-1 - (-s) - 0 - 2s = -1. $$

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Feb 5, 2026
@rustbot
Copy link
Collaborator

rustbot commented Feb 5, 2026

r? @scottmcm

rustbot has assigned @scottmcm.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@scottmcm

This comment was marked as resolved.

@rustbot rustbot assigned jhpratt and unassigned scottmcm Feb 17, 2026
@jhpratt
Copy link
Member

jhpratt commented Feb 18, 2026

Neat! I've never thought of that, but it actually may be useful for some code of my own.

@bors r+ rollup

@rust-bors
Copy link
Contributor

rust-bors bot commented Feb 18, 2026

📌 Commit 689e8c2 has been approved by jhpratt

It is now in the queue for this repository.

@rust-bors rust-bors bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 18, 2026
jhpratt added a commit to jhpratt/rust that referenced this pull request Feb 18, 2026
…=jhpratt

Add documentation note about signed overflow direction

In rust-lang#151989 (comment) I noticed that signed overflow direction can be determined by returned wrapped value. It is not very obvious (especially, assuming additional `carry: bool` summand), but it is important if we want to add new leading (signed) limb to big integer in this case.

Examples for small summands `x, y: i8` with result extension:

| x     | y    | overflow | result as (u8, i8) |
| ----  | ---- | -------- | ------------------ |
| -1    | -128 | true     | (127, -1)          |
| 0     | -1   | false    | (255, -1)          |
| 2     | 2    | false    | (4, 0)             |
| 127   | 1    | true     | (128, 0)           |

Here is general proof.

1. Set $s=2^{N-1}$ and let's say `iN::carrying_add(x, y, c)` returns `(result, true)` then

$$
\mathrm{result}=\begin{cases}
x + y + c + 2s,& x + y + c \le -s-1,\\
x+y+c-2s,& x+y+c\ge s.
\end{cases}
$$

First case is overflowing below `iN::MIN` and we have

$$
\mathrm{result}\ge -s-s+0+2s =0;\qquad
\mathrm{result}=x + y + c + 2s\le -s-1+2s = s - 1,
$$

so we obtain $[0; s-1]$ which is exactly range of non-negative `iN`.

Second case is overflowing above `iN::MAX` and

$$
\mathrm{result}=x+y+c-2s\ge s-2s =-s;\qquad
\mathrm{result}\le s-1 + s-1+1-2s = -1,
$$

that is, $[-s,-1]$ which is exactly range of negative `iN`.

2. Now suppose that `iN::borrowing_sub(x,y,b)` returns `(result, true)` then

$$
\mathrm{result}=\begin{cases}
x - y - b + 2s,& x - y - b \le -s-1,\\
x - y - b - 2s,& x - y - b\ge s.
\end{cases}
$$

First case is overflowing below `iN::MIN` and we have

$$
\mathrm{result}\ge -s-(s-1)-1+2s =0;\qquad
\mathrm{result}=x - y - b + 2s\le -s-1+2s = s - 1.
$$

Second case is overflowing above `iN::MAX` and

$$
\mathrm{result}=x-y-b-2s\ge s-2s =-s;\qquad
\mathrm{result}\le s-1 - (-s) - 0 - 2s = -1.
$$
jhpratt added a commit to jhpratt/rust that referenced this pull request Feb 18, 2026
…=jhpratt

Add documentation note about signed overflow direction

In rust-lang#151989 (comment) I noticed that signed overflow direction can be determined by returned wrapped value. It is not very obvious (especially, assuming additional `carry: bool` summand), but it is important if we want to add new leading (signed) limb to big integer in this case.

Examples for small summands `x, y: i8` with result extension:

| x     | y    | overflow | result as (u8, i8) |
| ----  | ---- | -------- | ------------------ |
| -1    | -128 | true     | (127, -1)          |
| 0     | -1   | false    | (255, -1)          |
| 2     | 2    | false    | (4, 0)             |
| 127   | 1    | true     | (128, 0)           |

Here is general proof.

1. Set $s=2^{N-1}$ and let's say `iN::carrying_add(x, y, c)` returns `(result, true)` then

$$
\mathrm{result}=\begin{cases}
x + y + c + 2s,& x + y + c \le -s-1,\\
x+y+c-2s,& x+y+c\ge s.
\end{cases}
$$

First case is overflowing below `iN::MIN` and we have

$$
\mathrm{result}\ge -s-s+0+2s =0;\qquad
\mathrm{result}=x + y + c + 2s\le -s-1+2s = s - 1,
$$

so we obtain $[0; s-1]$ which is exactly range of non-negative `iN`.

Second case is overflowing above `iN::MAX` and

$$
\mathrm{result}=x+y+c-2s\ge s-2s =-s;\qquad
\mathrm{result}\le s-1 + s-1+1-2s = -1,
$$

that is, $[-s,-1]$ which is exactly range of negative `iN`.

2. Now suppose that `iN::borrowing_sub(x,y,b)` returns `(result, true)` then

$$
\mathrm{result}=\begin{cases}
x - y - b + 2s,& x - y - b \le -s-1,\\
x - y - b - 2s,& x - y - b\ge s.
\end{cases}
$$

First case is overflowing below `iN::MIN` and we have

$$
\mathrm{result}\ge -s-(s-1)-1+2s =0;\qquad
\mathrm{result}=x - y - b + 2s\le -s-1+2s = s - 1.
$$

Second case is overflowing above `iN::MAX` and

$$
\mathrm{result}=x-y-b-2s\ge s-2s =-s;\qquad
\mathrm{result}\le s-1 - (-s) - 0 - 2s = -1.
$$
rust-bors bot pushed a commit that referenced this pull request Feb 18, 2026
Rollup of 19 pull requests

Successful merges:

 - #145399 (Unify wording of resolve error)
 - #150473 (tail calls: fix copying non-scalar arguments to callee)
 - #152637 (Add a note about elided lifetime)
 - #152657 (std: move `exit` out of PAL)
 - #152729 (compiler: Don't mark `SingleUseConsts` MIR pass as "required for soundness")
 - #152753 (remove the explicit error for old `rental` versions)
 - #152758 (Remove ShallowInitBox.)
 - #151530 (Fix invalid `mut T` suggestion for `&mut T` in missing lifetime error)
 - #152179 (Add documentation note about signed overflow direction)
 - #152474 (Implement opt-bisect-limit for MIR)
 - #152509 (tests/ui/test-attrs: add annotations for reference rules)
 - #152672 (std: use libc version of `_NSGetArgc`/`_NSGetArgv`)
 - #152711 (resolve: Disable an assert that no longer holds)
 - #152732 (add regression test for 147958)
 - #152745 (Fix ICE in `suggest_param_env_shadowing` with incompatible args)
 - #152749 (make `rustc_allow_const_fn_unstable` an actual `rustc_attrs` attribute)
 - #152756 (Miri: recursive validity: also recurse into Boxes)
 - #152770 (carryless_mul: mention the base)
 - #152778 (Update tracking issue number for final_associated_functions)
rust-bors bot pushed a commit that referenced this pull request Feb 18, 2026
Rollup of 20 pull requests

Successful merges:

 - #145399 (Unify wording of resolve error)
 - #150473 (tail calls: fix copying non-scalar arguments to callee)
 - #152637 (Add a note about elided lifetime)
 - #152729 (compiler: Don't mark `SingleUseConsts` MIR pass as "required for soundness")
 - #152751 (Rename dep node "fingerprints" to distinguish key and value hashes)
 - #152753 (remove the explicit error for old `rental` versions)
 - #152758 (Remove ShallowInitBox.)
 - #151530 (Fix invalid `mut T` suggestion for `&mut T` in missing lifetime error)
 - #152179 (Add documentation note about signed overflow direction)
 - #152474 (Implement opt-bisect-limit for MIR)
 - #152509 (tests/ui/test-attrs: add annotations for reference rules)
 - #152672 (std: use libc version of `_NSGetArgc`/`_NSGetArgv`)
 - #152711 (resolve: Disable an assert that no longer holds)
 - #152725 (Rework explanation of CLI lint level flags)
 - #152732 (add regression test for 147958)
 - #152745 (Fix ICE in `suggest_param_env_shadowing` with incompatible args)
 - #152749 (make `rustc_allow_const_fn_unstable` an actual `rustc_attrs` attribute)
 - #152756 (Miri: recursive validity: also recurse into Boxes)
 - #152770 (carryless_mul: mention the base)
 - #152778 (Update tracking issue number for final_associated_functions)
@rust-bors rust-bors bot merged commit ae196c7 into rust-lang:main Feb 18, 2026
11 checks passed
@rustbot rustbot added this to the 1.95.0 milestone Feb 18, 2026
rust-timer added a commit that referenced this pull request Feb 18, 2026
Rollup merge of #152179 - nickkuk:overflow-direction-note, r=jhpratt

Add documentation note about signed overflow direction

In #151989 (comment) I noticed that signed overflow direction can be determined by returned wrapped value. It is not very obvious (especially, assuming additional `carry: bool` summand), but it is important if we want to add new leading (signed) limb to big integer in this case.

Examples for small summands `x, y: i8` with result extension:

| x     | y    | overflow | result as (u8, i8) |
| ----  | ---- | -------- | ------------------ |
| -1    | -128 | true     | (127, -1)          |
| 0     | -1   | false    | (255, -1)          |
| 2     | 2    | false    | (4, 0)             |
| 127   | 1    | true     | (128, 0)           |

Here is general proof.

1. Set $s=2^{N-1}$ and let's say `iN::carrying_add(x, y, c)` returns `(result, true)` then

$$
\mathrm{result}=\begin{cases}
x + y + c + 2s,& x + y + c \le -s-1,\\
x+y+c-2s,& x+y+c\ge s.
\end{cases}
$$

First case is overflowing below `iN::MIN` and we have

$$
\mathrm{result}\ge -s-s+0+2s =0;\qquad
\mathrm{result}=x + y + c + 2s\le -s-1+2s = s - 1,
$$

so we obtain $[0; s-1]$ which is exactly range of non-negative `iN`.

Second case is overflowing above `iN::MAX` and

$$
\mathrm{result}=x+y+c-2s\ge s-2s =-s;\qquad
\mathrm{result}\le s-1 + s-1+1-2s = -1,
$$

that is, $[-s,-1]$ which is exactly range of negative `iN`.

2. Now suppose that `iN::borrowing_sub(x,y,b)` returns `(result, true)` then

$$
\mathrm{result}=\begin{cases}
x - y - b + 2s,& x - y - b \le -s-1,\\
x - y - b - 2s,& x - y - b\ge s.
\end{cases}
$$

First case is overflowing below `iN::MIN` and we have

$$
\mathrm{result}\ge -s-(s-1)-1+2s =0;\qquad
\mathrm{result}=x - y - b + 2s\le -s-1+2s = s - 1.
$$

Second case is overflowing above `iN::MAX` and

$$
\mathrm{result}=x-y-b-2s\ge s-2s =-s;\qquad
\mathrm{result}\le s-1 - (-s) - 0 - 2s = -1.
$$
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

Comments