-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracking issue for std::num::NonZero* types #49137
Comments
Implementation PR: #48265 Documentation: @Centril, do doc-comments in this PR look sufficient to you? My opinion on unresolved questions: Signed types (e.g.
Dropping the Separate types v.s. one generic type: this was discussed at length in the RFC. The former has precedent with |
Making the memory layout of |
Pretty much, yeah =) On the unresolved questions:
|
For what it’s worth the implementation of the 6 signed types costs exactly an additional 111 characters in a macro invocation. They’re not a maintenance burden. |
This is true; but they cost in compile times -- but probably not a noteworthy amount of time. |
Honestly, compile time of end-user crates matters a lot more than compile time of libstd and co. because for most users libstd will already be compiled. So, even adding a minute of compile time to libstd isn't super bad. |
Sounds like I'm the only one who likes Maybe just put the signed ones under a different feature gate? That way we'll find out which ones people use, and there's still nobody "attached" to them, stabilize/remove them separately. (Personally I think |
I honestly think that
|
Add 12 num::NonZero* types for primitive integers, deprecate core::nonzero RFC: rust-lang/rfcs#2307 Tracking issue: ~~rust-lang#27730 rust-lang#49137 Fixes rust-lang#27730
Add 12 num::NonZero* types for primitive integers, deprecate core::nonzero RFC: rust-lang/rfcs#2307 Tracking issue: ~~rust-lang#27730 rust-lang#49137 Fixes rust-lang#27730
The implementation #48265 has landed, it should reach Nightly in a few hours. |
@SimonSapin how do you feel about @scottmcm's note that we should:
|
How useful is this to do now? (v.s. changing the status later of only a subset) My thoughts lately on the signed types is that there isn’t really a strong case against them, but there isn’t much of a use case either. Adding that they can be easily be built out of tree on top of the unsigned types, I’d be ok with removing or deprecating them and see if anyone objects. They’re easy to add (back) later if we decide to do so. |
👍 |
… gated on the `unstable` Cargo feature. These are new standard library types. Tracking issue: rust-lang/rust#49137
… gated on the `unstable` Cargo feature. These are new standard library types. Tracking issue: rust-lang/rust#49137
Deprecation of NonZeroI* #49324 Support for NonZeroU* in serde: serde-rs/serde#1191 |
Would using an unsafe trait to specify invalid ranges be viable? I think traits are a great way to specify interfaces, so that idea appeals to me at least from this point of view. Example:
It would allow users to specify arbitrary invalid bit patterns. That way we could even have things like:
What do you think? |
@Kixunil Using just associated Using methods is a no-no, it means you're getting no LLVM optimization (), no nested reuse (for the same reason IMO the only reliable way to get this is const generics and a wrapper type that removes a values of a certain width (or just full width), at a certain location (or just offset 0), from the type.
Sure. But this is not an interface, it's a fundamental representational property of the data type. In your case, who's stopping me from creating |
@eddyb Could you give an example of weird inconsistency that might happen? People can already shoot themselves in the foot in unsafe code. I don't see a problem with careful use of
Why? If LLVM can optimize some functions, what's preventing it from optimizing other functions?
Why one const fn works in miri but not other const fn?
would using
What's preventing me to implement e.g.
|
The problem is a trait impl is not "inherent" to a type. We'd have to pile on a bunch of checks, to ensure impls of this trait are "boring" wrt to when they hold. Most importantly, the implementation must not depend on type parameters, nor introduce relationships between lifetime parameters (or just not have generic parameters at all). In a way, this is similar to the restrictions of the With all of that work, and
I mean we can't tell LLVM anything about value validity, if you have functions doing encoding and decoding. Our existing contiguous "(in)valid ranges" actually lower to LLVM
We don't have
Sure, but you actually want a custom union between
I personally have no intention of supporting those kinds of optimizations. they can significantly complicate discriminant decoding (which happens at runtime, unlike encoding), whereas, currently, all of our enums, even when using invalid values, take at most one subtraction and one comparison, to decode the discriminant. |
That makes a lot more sense to me now, thanks for explaining! |
Somewhere else (the PR that deprecated them) one is requested to drop in here and indicate if you use (or would use, I guess) signed NonZero variants. I do / would, lots. The most common use case is in differential dataflow (but it is probably more common) where you record changes to things. You don't ever need to record a zero change, and indeed often you want to use types to communicate the non-zero'd ness. For example, I'd love to be using a trait trait Addition {
/// returns the result of the summation if non-zero.
fn add(self, other: Self) -> Option<Self>;
} The important point for me is that I'd like the opportunity for the zero value to not inhabit the types, so that e.g. Without non-zero signed integers, the above Anyhow, I can work around forever, obvs, but I thought you all might want to know! :D |
@frankmcsherry FWIW this should be sufficient: #[derive(Copy, Clone)]
pub struct NonZeroI32(NonZeroU32);
impl NonZeroI32 {
pub fn new(x: i32) -> Option<Self> {
NonZeroU32::new(x as u32).map(NonZeroI32)
}
pub fn get(self) -> i32 {
self.0.get() as i32
}
} |
There is also a crate implementing signed NonZero type |
Yup, thank you! I'm def happy working around, but equally happy to let you folks know about use cases (and if other people have them, put something like this next to |
Given the existence of a work-around that preserves the enum layout optimization, this doesn’t seem very pressing. On the other hand, adding them is very easy, and not really any additional maintenance burden. So I’m really neutral on this one. Consider nagging some other member of the libs team :) |
This is probably more amusing than significant, but another real-world use case of signed-numbers-without-zero is years. |
Another use case for signed non-zero numbers: I'm currently working with a C library where the number 0 is significant. Representing this as an enum would probably work well I reckon. libnghttp2_sys API ExampleAn example of how to represent the pub type StreamId = NonZeroI32;
pub enum StreamDependency {
Independent,
Dependent(StreamId),
} |
For now, can't signed nonzero types just be implemented as a separate crate? Then people can judge inclusion into libstd based upon how many people use it. |
Yes, https://crates.io/crates/nonzero_signed was mentioned upthread. |
...oh. In that case, perhaps this issue could be locked from future comments on that and a larger note could be made to mention that crate? |
#57475 Add signed num::NonZeroI* types |
Multiple people have asked for them, in rust-lang#49137. Given that the unsigned ones already exist, they are very easy to add and not an additional maintenance burden.
Add signed num::NonZeroI* types Multiple people have asked for them in rust-lang#49137. Given that the unsigned ones already exist, they are very easy to add and not an additional maintenance burden.
Add signed num::NonZeroI* types Multiple people have asked for them in #49137. Given that the unsigned ones already exist, they are very easy to add and not an additional maintenance burden.
Multiple people have asked for them, in rust-lang#49137. Given that the unsigned ones already exist, they are very easy to add and not an additional maintenance burden.
Will this ever be available to users? |
This is a tracking issue for the RFC "Add std::num::NonZeroU32 and friends, deprecate core::nonzero" (rust-lang/rfcs#2307).
Steps:
Unresolved questions:
NonZeroU32
orPositiveU32
? Should theU
be dropped?-- We should either end up with a generic type or with a clear explanation of why a generic type can't work or doesn't work well.
The text was updated successfully, but these errors were encountered: