You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently, there is no way to obtain a NonZero* value without introducing unsafe codes or unwrap() calls, providing these constants can make it easier to use these types. For example:
use std::num::NonZeroU64;fnfoo(x:u64) -> NonZeroU64{
x.checked_add(1).and_then(NonZeroU64::new).unwrap_or(NonZeroU64::MAX)}
Not that I mind the addition of these constants in general, but your motivating example is a bit unfortunate in that it's a slightly obfuscated saturating_add. It would be better served by:
#![feature(nonzero_ops)]use std::num::NonZeroU64;pubfnbaz(x:u64) -> NonZeroU64{NonZeroU64::new(1).unwrap().saturating_add(x)// or `NonZeroU64::new(x.saturating_add(1)).unwrap()` if you need a solution on stable}
Yes, that does contain an unwrap, but it's provably unreachable and really the right tool for the job here. (Slightly better codegen too https://rust.godbolt.org/z/Tansn3Y61)
There are projects that forbid the usage of unwrap with Clippy. Using unwrap will require explicit #[allow(...)] attribute and maybe proper comment, which seems a little too much.
This might just be my head being in a more Ada space, but not having immediate access to the MIN and MAX for a given scalar type feels wrong to me. Obviously with a little forethought you can come up with a totally safe unwrap, but when you're doing something simple like initializing values for a comparison algorithm, it seems like it might be a bit better if you can use a constant which took care of that thinking about safety for you.
but when you're doing something simple like initializing values for a comparison algorithm
is a good motivating example if you ask me.
@EFanZh: Sounds like these projects blanket forbid unwrap as a very coarse heuristic for the behavior they actually want to disallow. If this unwanted behavior is "there is an input that causes the program to panic (ignoring OOM)", you could teach Clippy to allow unwrap in const contexts. That way you get a compilation error if the panic path ever fires. The example you provided would then look like:
Of course that currently requires nightly features and not sure how hard it would be to improve Clippy. Hopefully that will become viable for stable projects soon.
Some interrelated thoughts on the stated problems this is trying to solve:
NonZeroI*::{MIN,MAX} are a little weird, because in all other integer cases, all integers between MIN and MAX exist, but in the case of nonzero signed integers, there's also a hole in the middle. This seems an oddity worth thinking about and possibly documenting.
I also notice that the code example at the beginning of this thread cannot be written using these constants for NonZeroI* because while NonZeroU*::MIN is 1, NonZeroI*::MIN is not. Also the code would be clearer in both cases if the value was named ONE rather than MIN. This suggests to me that possibly there should be a ONE constant for NonZero types, or at least the signed ones.
If there were to be ONE, then the question of why not TWO, TEN, etc. comes up. The plausible response to adding any of them is "it's all moot once const panics are stable", but NonZeroI64::new(5).unwrap() is still a long and tedious bit of code to write whenever you want a number literal. It would be nice if there was a specific or general way to improve such fallible-but-only-at-compile-time code. (I have some thoughts on this but they're further off-topic for this issue.)
(None of this is intended to argue that MIN and MAX shouldn't be added.)
I like the points @kpreid made. I would concur that ONE as a constant might be useful, but should not be instead of a MIN, even for the signed integers. I think having the lowest possible value clearly demarcated as such has value.
(It would be kinda nice to have a fast way of making number literals of this type. I think that would probably help with adoption. Feel free to tag me if you open an issue!)
NonZeroI*::{MIN,MAX} are a little weird, because in all other integer cases, all integers between MIN and MAX exist, but in the case of nonzero signed integers, there's also a hole in the middle. This seems an oddity worth thinking about and possibly documenting.
Agreed.
I also notice that the code example at the beginning of this thread cannot be written using these constants for NonZeroI* because while NonZeroU*::MIN is 1, NonZeroI*::MIN is not. Also the code would be clearer in both cases if the value was named ONE rather than MIN. This suggests to me that possibly there should be a ONE constant for NonZero types, or at least the signed ones.
Not sure I follow. The code example at the beginning used MAX and not MIN. Yes, it does happen to add 1 - which incidentally also happens to be the value of NonZeroU*::MIN - so you technically could implement the given example as:
use std::num::NonZeroU64;pubfnbax(x:u64) -> NonZeroU64{NonZeroU64::MIN.saturating_add(x)}
Luckily, I haven't seen anybody propose such a gross abuse of the MIN constant.
If there were to be ONE, then the question of why not TWO, TEN, etc. comes up. The plausible response to adding any of them is "it's all moot once const panics are stable", but NonZeroI64::new(5).unwrap() is still a long and tedious bit of code to write whenever you want a number literal. It would be nice if there was a specific or general way to improve such fallible-but-only-at-compile-time code. (I have some thoughts on this but they're further off-topic for this issue.)
Yes, getting a literal NonZero* is currently overly clunky and should be made easier and quicker. No doubt about that, but adding otherwise meaningless constants (be it ONE or TWO or TEN) isn't a good solution. Not sure how solutions could look that that are both ergonomic and feasible, but that's indeed going too far off-topic. If you end up writing down your thoughts on that, kindly cc me.
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
Activity
mjclements commentedon Sep 18, 2021
I think this sounds like a good feature, and I would like to claim it for a first contribution.
mjclements commentedon Sep 18, 2021
@rustbot claim
LingMan commentedon Sep 19, 2021
Not that I mind the addition of these constants in general, but your motivating example is a bit unfortunate in that it's a slightly obfuscated
saturating_add. It would be better served by:Yes, that does contain an
unwrap, but it's provably unreachable and really the right tool for the job here. (Slightly better codegen too https://rust.godbolt.org/z/Tansn3Y61)EFanZh commentedon Sep 19, 2021
There are projects that forbid the usage of
unwrapwith Clippy. Usingunwrapwill require explicit#[allow(...)]attribute and maybe proper comment, which seems a little too much.mjclements commentedon Sep 19, 2021
This might just be my head being in a more Ada space, but not having immediate access to the MIN and MAX for a given scalar type feels wrong to me. Obviously with a little forethought you can come up with a totally safe unwrap, but when you're doing something simple like initializing values for a comparison algorithm, it seems like it might be a bit better if you can use a constant which took care of that thinking about safety for you.
LingMan commentedon Sep 20, 2021
@mjclements: Thank you. This:
is a good motivating example if you ask me.
@EFanZh: Sounds like these projects blanket forbid
unwrapas a very coarse heuristic for the behavior they actually want to disallow. If this unwanted behavior is "there is an input that causes the program to panic (ignoring OOM)", you could teach Clippy to allowunwrapin const contexts. That way you get a compilation error if the panic path ever fires. The example you provided would then look like:Of course that currently requires nightly features and not sure how hard it would be to improve Clippy. Hopefully that will become viable for stable projects soon.
kpreid commentedon Sep 20, 2021
Some interrelated thoughts on the stated problems this is trying to solve:
NonZeroI*::{MIN,MAX}are a little weird, because in all other integer cases, all integers between MIN and MAX exist, but in the case of nonzero signed integers, there's also a hole in the middle. This seems an oddity worth thinking about and possibly documenting.I also notice that the code example at the beginning of this thread cannot be written using these constants for
NonZeroI*because whileNonZeroU*::MINis 1,NonZeroI*::MINis not. Also the code would be clearer in both cases if the value was namedONErather thanMIN. This suggests to me that possibly there should be aONEconstant for NonZero types, or at least the signed ones.ONE, then the question of why notTWO,TEN, etc. comes up. The plausible response to adding any of them is "it's all moot once const panics are stable", butNonZeroI64::new(5).unwrap()is still a long and tedious bit of code to write whenever you want a number literal. It would be nice if there was a specific or general way to improve such fallible-but-only-at-compile-time code. (I have some thoughts on this but they're further off-topic for this issue.)(None of this is intended to argue that
MINandMAXshouldn't be added.)mjclements commentedon Sep 21, 2021
I like the points @kpreid made. I would concur that ONE as a constant might be useful, but should not be instead of a MIN, even for the signed integers. I think having the lowest possible value clearly demarcated as such has value.
(It would be kinda nice to have a fast way of making number literals of this type. I think that would probably help with adoption. Feel free to tag me if you open an issue!)
LingMan commentedon Sep 21, 2021
Agreed.
Not sure I follow. The code example at the beginning used
MAXand notMIN. Yes, it does happen to add 1 - which incidentally also happens to be the value ofNonZeroU*::MIN- so you technically could implement the given example as:Luckily, I haven't seen anybody propose such a gross abuse of the
MINconstant.Yes, getting a literal
NonZero*is currently overly clunky and should be made easier and quicker. No doubt about that, but adding otherwise meaningless constants (be itONEorTWOorTEN) isn't a good solution. Not sure how solutions could look that that are both ergonomic and feasible, but that's indeed going too far off-topic. If you end up writing down your thoughts on that, kindly cc me.Rollup merge of rust-lang#93293 - nvzqz:nonzero-min-max, r=joshtriplett
nvzqz commentedon Mar 12, 2022
This is now available on nightly (docs).
[-]Add `NonZero{I,U}{8,16,32,64,128}::{MIN,MAX}`[/-][+]Add `NonZero{I,U}{8,16,32,64,128,size}::{MIN,MAX}`[/+]gilescope commentedon Apr 11, 2022
Excellent, glad these have landed. Am discussing having these MIN/MAX available from traits:
https://internals.rust-lang.org/t/please-can-we-add-a-basic-num-trait/16449/9
c410-f3r commentedon Jul 22, 2022
Is there anything blocking the stabilization of this feature?
4 remaining items
rfcbot commentedon Jan 23, 2023
Team member @dtolnay has proposed to merge this. The next step is review by the rest of the tagged team members:
No concerns currently listed.
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
rfcbot commentedon Feb 28, 2023
🔔 This is now entering its final comment period, as per the review above. 🔔
rfcbot commentedon Mar 10, 2023
The final comment period, with a disposition to merge, as per the review above, is now complete.
As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.
This will be merged soon.
Rollup merge of rust-lang#106633 - c410-f3r:stabilize-nonzero_bits, r…
Rollup merge of rust-lang#106633 - c410-f3r:stabilize-nonzero_bits, r…
Rollup merge of #106633 - c410-f3r:stabilize-nonzero_bits, r=dtolnay