Add generic `NonZero` type. by reitermarkus · Pull Request #100428 · rust-lang/rust

@rustbot rustbot added the T-libs

Relevant to the library team, which will review and decide on the PR/issue.

label

Aug 11, 2022

reitermarkus

reitermarkus

dtolnay

@rustbot rustbot added S-waiting-on-author

Status: This is awaiting some action (such as code changes or more information) from the author.

and removed S-waiting-on-review

Status: Awaiting review from the assignee but also interested parties.

labels

Dec 6, 2023

@dtolnay dtolnay added S-blocked

Status: Blocked on something else such as an RFC or other implementation work.

and removed S-waiting-on-author

Status: This is awaiting some action (such as code changes or more information) from the author.

labels

Jan 15, 2024

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request

Jan 16, 2024
…=dtolnay

Add private `NonZero<T>` type alias.

According to step 2 suggested in rust-lang#100428 (review).

This adds a private type alias for `NonZero<T>` so that some parts of the code can already start using `NonZero<T>` syntax.

Using `NonZero<T>` for `convert` and other parts which implement `From` doesn't work while it is a type alias, since this results in conflicting implementations.

rust-timer added a commit to rust-lang-ci/rust that referenced this pull request

Jan 16, 2024
Rollup merge of rust-lang#119990 - reitermarkus:nonzero-type-alias, r=dtolnay

Add private `NonZero<T>` type alias.

According to step 2 suggested in rust-lang#100428 (review).

This adds a private type alias for `NonZero<T>` so that some parts of the code can already start using `NonZero<T>` syntax.

Using `NonZero<T>` for `convert` and other parts which implement `From` doesn't work while it is a type alias, since this results in conflicting implementations.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request

Jan 19, 2024
Consolidate all associated items on the NonZero integer types into a single impl block per type

**Before:**

```rust
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
pub struct NonZeroI8(i8);

impl NonZeroI8 {
    pub const fn new(n: i8) -> Option<Self> ...
    pub const fn get(self) -> i8 ...
}

impl NonZeroI8 {
    pub const fn leading_zeros(self) -> u32 ...
    pub const fn trailing_zeros(self) -> u32 ...
}

impl NonZeroI8 {
    pub const fn abs(self) -> NonZeroI8 ...
}
...
```

**After:**

```rust
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
pub struct NonZeroI8(i8);

impl NonZeroI8 {
    pub const fn new(n: i8) -> Option<Self> ...
    pub const fn get(self) -> i8 ...
    pub const fn leading_zeros(self) -> u32 ...
    pub const fn trailing_zeros(self) -> u32 ...
    pub const fn abs(self) -> NonZeroI8 ...
    ...
}
```

Having 6-7 different impl blocks per type is not such a problem in today's implementation, but becomes awful upon the switch to a generic `NonZero<T>` type (context: rust-lang#82363 (comment)).

In the implementation from rust-lang#100428, there end up being **67** impl blocks on that type.

<img src="https://github.com/rust-lang/rust/assets/1940490/5b68bd6f-8a36-4922-baa3-348e30dbfcc1" width="200"><img src="https://github.com/rust-lang/rust/assets/1940490/2cfec71e-c2cd-4361-a542-487f13f435d9" width="200"><img src="https://github.com/rust-lang/rust/assets/1940490/2fe00337-7307-405d-9036-6fe1e58b2627" width="200">

Without the refactor to a single impl block first, introducing `NonZero<T>` would be a usability regression compared to today's separate pages per type. With all those blocks expanded, Ctrl+F is obnoxious because you need to skip 12&times; past every match you don't care about. With all the blocks collapsed, Ctrl+F is useless. Getting to a state in which exactly one type's (e.g. `NonZero<u32>`) impl blocks are expanded while the rest are collapsed is annoying.

After this refactor to a single impl block, we can move forward with making `NonZero<T>` a generic struct whose docs all go on the same rustdoc page. The rustdoc will have 12 impl blocks, one per choice of `T` supported by the standard library. The reader can expand a single one of those impl blocks e.g. `NonZero<u32>` to understand the entire API of that type.

Note that moving the API into a generic `impl<T> NonZero<T> { ... }` is not going to be an option until after `NonZero<T>` has been stabilized, which may be months or years after its introduction. During the period while generic `NonZero` is unstable, it will be extra important to offer good documentation on all methods demonstrating the API being used through the stable aliases such as `NonZeroI8`.

This PR follows a `key = $value` syntax for the macros which is similar to the macros we already use for producing a single large impl block on the integer primitives.

https://github.com/rust-lang/rust/blob/1dd4db50620fb38a6382c22456a96ed7cddeff83/library/core/src/num/mod.rs#L288-L309

Best reviewed one commit at a time.

rust-timer added a commit to rust-lang-ci/rust that referenced this pull request

Jan 19, 2024
Rollup merge of rust-lang#118665 - dtolnay:signedness, r=Nilstrieb

Consolidate all associated items on the NonZero integer types into a single impl block per type

**Before:**

```rust
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
pub struct NonZeroI8(i8);

impl NonZeroI8 {
    pub const fn new(n: i8) -> Option<Self> ...
    pub const fn get(self) -> i8 ...
}

impl NonZeroI8 {
    pub const fn leading_zeros(self) -> u32 ...
    pub const fn trailing_zeros(self) -> u32 ...
}

impl NonZeroI8 {
    pub const fn abs(self) -> NonZeroI8 ...
}
...
```

**After:**

```rust
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
pub struct NonZeroI8(i8);

impl NonZeroI8 {
    pub const fn new(n: i8) -> Option<Self> ...
    pub const fn get(self) -> i8 ...
    pub const fn leading_zeros(self) -> u32 ...
    pub const fn trailing_zeros(self) -> u32 ...
    pub const fn abs(self) -> NonZeroI8 ...
    ...
}
```

Having 6-7 different impl blocks per type is not such a problem in today's implementation, but becomes awful upon the switch to a generic `NonZero<T>` type (context: rust-lang#82363 (comment)).

In the implementation from rust-lang#100428, there end up being **67** impl blocks on that type.

<img src="https://github.com/rust-lang/rust/assets/1940490/5b68bd6f-8a36-4922-baa3-348e30dbfcc1" width="200"><img src="https://github.com/rust-lang/rust/assets/1940490/2cfec71e-c2cd-4361-a542-487f13f435d9" width="200"><img src="https://github.com/rust-lang/rust/assets/1940490/2fe00337-7307-405d-9036-6fe1e58b2627" width="200">

Without the refactor to a single impl block first, introducing `NonZero<T>` would be a usability regression compared to today's separate pages per type. With all those blocks expanded, Ctrl+F is obnoxious because you need to skip 12&times; past every match you don't care about. With all the blocks collapsed, Ctrl+F is useless. Getting to a state in which exactly one type's (e.g. `NonZero<u32>`) impl blocks are expanded while the rest are collapsed is annoying.

After this refactor to a single impl block, we can move forward with making `NonZero<T>` a generic struct whose docs all go on the same rustdoc page. The rustdoc will have 12 impl blocks, one per choice of `T` supported by the standard library. The reader can expand a single one of those impl blocks e.g. `NonZero<u32>` to understand the entire API of that type.

Note that moving the API into a generic `impl<T> NonZero<T> { ... }` is not going to be an option until after `NonZero<T>` has been stabilized, which may be months or years after its introduction. During the period while generic `NonZero` is unstable, it will be extra important to offer good documentation on all methods demonstrating the API being used through the stable aliases such as `NonZeroI8`.

This PR follows a `key = $value` syntax for the macros which is similar to the macros we already use for producing a single large impl block on the integer primitives.

https://github.com/rust-lang/rust/blob/1dd4db50620fb38a6382c22456a96ed7cddeff83/library/core/src/num/mod.rs#L288-L309

Best reviewed one commit at a time.

github-actions bot pushed a commit to rust-lang/miri that referenced this pull request

Jan 21, 2024
Consolidate all associated items on the NonZero integer types into a single impl block per type

**Before:**

```rust
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
pub struct NonZeroI8(i8);

impl NonZeroI8 {
    pub const fn new(n: i8) -> Option<Self> ...
    pub const fn get(self) -> i8 ...
}

impl NonZeroI8 {
    pub const fn leading_zeros(self) -> u32 ...
    pub const fn trailing_zeros(self) -> u32 ...
}

impl NonZeroI8 {
    pub const fn abs(self) -> NonZeroI8 ...
}
...
```

**After:**

```rust
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
pub struct NonZeroI8(i8);

impl NonZeroI8 {
    pub const fn new(n: i8) -> Option<Self> ...
    pub const fn get(self) -> i8 ...
    pub const fn leading_zeros(self) -> u32 ...
    pub const fn trailing_zeros(self) -> u32 ...
    pub const fn abs(self) -> NonZeroI8 ...
    ...
}
```

Having 6-7 different impl blocks per type is not such a problem in today's implementation, but becomes awful upon the switch to a generic `NonZero<T>` type (context: rust-lang/rust#82363 (comment)).

In the implementation from rust-lang/rust#100428, there end up being **67** impl blocks on that type.

<img src="https://github.com/rust-lang/rust/assets/1940490/5b68bd6f-8a36-4922-baa3-348e30dbfcc1" width="200"><img src="https://github.com/rust-lang/rust/assets/1940490/2cfec71e-c2cd-4361-a542-487f13f435d9" width="200"><img src="https://github.com/rust-lang/rust/assets/1940490/2fe00337-7307-405d-9036-6fe1e58b2627" width="200">

Without the refactor to a single impl block first, introducing `NonZero<T>` would be a usability regression compared to today's separate pages per type. With all those blocks expanded, Ctrl+F is obnoxious because you need to skip 12&times; past every match you don't care about. With all the blocks collapsed, Ctrl+F is useless. Getting to a state in which exactly one type's (e.g. `NonZero<u32>`) impl blocks are expanded while the rest are collapsed is annoying.

After this refactor to a single impl block, we can move forward with making `NonZero<T>` a generic struct whose docs all go on the same rustdoc page. The rustdoc will have 12 impl blocks, one per choice of `T` supported by the standard library. The reader can expand a single one of those impl blocks e.g. `NonZero<u32>` to understand the entire API of that type.

Note that moving the API into a generic `impl<T> NonZero<T> { ... }` is not going to be an option until after `NonZero<T>` has been stabilized, which may be months or years after its introduction. During the period while generic `NonZero` is unstable, it will be extra important to offer good documentation on all methods demonstrating the API being used through the stable aliases such as `NonZeroI8`.

This PR follows a `key = $value` syntax for the macros which is similar to the macros we already use for producing a single large impl block on the integer primitives.

https://github.com/rust-lang/rust/blob/1dd4db50620fb38a6382c22456a96ed7cddeff83/library/core/src/num/mod.rs#L288-L309

Best reviewed one commit at a time.

TaKO8Ki added a commit to TaKO8Ki/rust that referenced this pull request

Jan 21, 2024
…lnay

Manually implement derived `NonZero` traits.

Step 3 as mentioned in rust-lang#100428 (review).

Manually implement the traits that would cause “borrow of layout constrained field with interior mutability” errors when switching to `NonZero<T>`.

r? `@dtolnay`

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request

Jan 22, 2024
…lnay

Manually implement derived `NonZero` traits.

Step 3 as mentioned in rust-lang#100428 (review).

Manually implement the traits that would cause “borrow of layout constrained field with interior mutability” errors when switching to `NonZero<T>`.

r? `@dtolnay`

fmease added a commit to fmease/rust that referenced this pull request

Jan 23, 2024
…lnay

Manually implement derived `NonZero` traits.

Step 3 as mentioned in rust-lang#100428 (review).

Manually implement the traits that would cause “borrow of layout constrained field with interior mutability” errors when switching to `NonZero<T>`.

r? ``@dtolnay``

fmease added a commit to fmease/rust that referenced this pull request

Jan 23, 2024
…lnay

Manually implement derived `NonZero` traits.

Step 3 as mentioned in rust-lang#100428 (review).

Manually implement the traits that would cause “borrow of layout constrained field with interior mutability” errors when switching to `NonZero<T>`.

r? ```@dtolnay```

rust-timer added a commit to rust-lang-ci/rust that referenced this pull request

Jan 24, 2024
Rollup merge of rust-lang#120160 - reitermarkus:nonzero-traits, r=dtolnay

Manually implement derived `NonZero` traits.

Step 3 as mentioned in rust-lang#100428 (review).

Manually implement the traits that would cause “borrow of layout constrained field with interior mutability” errors when switching to `NonZero<T>`.

r? ```@dtolnay```

fmease added a commit to fmease/rust that referenced this pull request

Jan 24, 2024

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request

Jan 25, 2024

bors added a commit to rust-lang-ci/rust that referenced this pull request

Jan 26, 2024

bors added a commit to rust-lang-ci/rust that referenced this pull request

Jan 27, 2024

bors added a commit to rust-lang-ci/rust that referenced this pull request

Jan 28, 2024

bors added a commit to rust-lang-ci/rust that referenced this pull request

Jan 29, 2024

github-actions bot pushed a commit to rust-lang/miri that referenced this pull request

Jan 31, 2024