-
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 const generics (RFC 2000) #44580
Comments
#44275 added a @EpicatSupercell has expressed interest in working on this, I'll mentor them through the initial implementation. However, we can't go too far because of the limitations described in #44275. That is, we need @nikomatsakis' lazy normalization to allow constant expressions embedded in types to observe the bounds in scope (from the function / type definition / impl / etc. item they're in), without producing cyclic dependencies half the time. |
Implementation waypoints (for more direct mentoring, seek
Note that all of this should allow |
I'd like to take a stab at this :) |
@samsartor there was a refactoring that had to be done before the main implementation work. That is now almost done (I'm waiting for feedback currently). I don't actually know how much work there is after that. Parsing const params was what I started with initially, before the refactoring. It's not done but I should be able to get that done relatively soon. |
@jplatte It would be nice, if you could link the pull request. I was not able to find it. |
There is no PR yet. All my work can be found here. |
Nice work so far @jplatte 🍻 |
There is now a PR for the groundwork ( |
I think this is already included but it would be good to handle the C++ style folding for handling linear algebra style n dimensional arrays with varying lengths, I.E. a 4x4 [[f64;4];4]or a 4x3x5x6 dimensional array [[[[f64;6];5];3];4] and be able to properly wrap and generate specialized methods for both it AND proper trait implementations for scalars properly dimensioned vectors, etc. See https://gist.github.com/huhlig/8b21850b54a75254be4b093551f8c2cb for a rudamentary example. |
I don't recall anyone proposing fold expressions for Rust before, much less as part of this RFC. But since this is Rust, is there any reason we couldn't implement fold expressions as an ordinary macro, rather than new dedicated syntax? |
What I mean is, if you want to refactor typical parser code like the following for reuse: let mut result: u32 = 0;
let mut digits = 0;
while digits < max_digits && src.has_remaining() {
match src.get_u8() {
d@b'0'..=b'9' => {
result = result*10 + (d - b'0') as u32;
digits += 1;
},
b'>' => match result {
0..=191 => break, // valid range
_ => return Err(DecoderError::OutOfRange),
},
_ => return Err(DecoderError::Malformed)
}
} You would typically move it out to a function, except the following won't work because certain values that are used in pattern matching have become variables: #[inline(always)]
fn read_str_digits<B: bytes::buf::Buf>(src: &mut B, stop_word: u8,
max_digits: u8, min_value: u32, max_value: u32) -> Result<u32, DecoderError> {
let mut result: u32 = 0;
let mut digits = 0;
while digits < max_digits && src.has_remaining() {
match src.get_u8() {
d@b'0'..=b'9' => {
result = result*10 + (d - b'0') as u32;
digits += 1;
},
stop_word => match result {
min_value..=max_value => break, // valid range
_ => return Err(DecoderError::OutOfRange),
},
_ => return Err(DecoderError::Malformed)
}
}
...
} If const generics lands before const arguments, I can suddenly abuse const generics to come up with the following: #[inline(always)]
fn read_str_digits<const MinValue: u32, const MaxValue: u32, const StopWord: u8, B: bytes::buf::Buf>
(src: &mut B, max_digits: u8) -> Result<u32, DecoderError> {
let mut result: u32 = 0;
let mut digits = 0;
while digits < max_digits && src.has_remaining() {
match src.get_u8() {
d@b'0'..=b'9' => {
result = result*10 + (d - b'0') as u32;
digits += 1;
},
StopWord => match result {
MinValue..=MaxValue => break, // valid range
_ => return Err(DecoderError::OutOfRange),
},
_ => return Err(DecoderError::Malformed)
}
}
...
} As of today, even this code won't work because the compiler does not detect the const generic values to be constants valid for use in a pattern, but that is obviously incorrect and needs to be addressed before RFC 2000 can land. Don't get me wrong, I've been fighting for generic constants for years and I have PRs ready to go for a dozen major crates (I can't wait to make the timezone in It's not necessarily the end of the world, but without having dug too deeply into it, it does seem as if a proper and complete const generics implementation will necessarily include all the plumbing for const arguments anyway, so we might as well take the extra time to finalize the syntax/ux/story for const arguments while we're at it and avoid an unfortunate era of code stink. Yes, the above can still be done with macros, but the ergonomics of const generics are a thousand times easier. fwiw, this is how I'd imagine the const argument version to look like: #[inline(always)]
fn read_str_digits<B: Bytes>(src: &mut B, min_value: const u32,
max_value: const u32, stop_word: const u8, max_digits: u8) -> Result<u32, ()> {
let mut result: u32 = 0;
let mut digits = 0;
while digits < max_digits && src.has_remaining() {
match src.get_u8() {
d@b'0'..=b'9' => {
result = result*10 + (d - b'0') as u32;
digits += 1;
},
stop_word => match result {
min_value..=max_value => break, // valid range
_ => return Err(()),
},
_ => return Err(())
}
}
...
} It would virtually be identical to const generics but for the semantics. |
This seems like a use-case that is more readily addressed by allowing the values of bound variables to be used in patterns (not just consts), with some new syntax. The fact that consts are currently allowed in patterns is counter-intuitive and, as far as I'm aware, historical. |
@mqudsi Forgive me if this is a silly question, but I don't see anything wrong about the example you gave. It looks like a perfectly valid use case for const generics to me: having a definition that is generalized to work with arbitrary values as the max/min. I don't really see the benefits of const arguments over const generics. They seem equivalent to me; that is, const arguments could just be implemented as a desugaring to const generics. Could you elaborate more on what's wrong with this design pattern? |
Here's a summary of the work on const generics since the last update. Last time, it was all about the core implementation: making sure everything fitted together and getting some of the basic test cases passing. Since then, the effort has been focused on making const generics more reliable: fixing cases that crashed the compiler, or didn't work unexpectedly, or improving diagnostics. We're getting closer to something that works reliably, though there's still a way to go.
Additionally, other work on the compiler ended up fixing some of the other issues relating to const generics. We've also started using const generics inside the compiler itself: array trait implementations now use const generics thanks to the work of @crlf0710 and @scottmcm (#60466, #62435), which led to performance improvements, and which will also allow us to unrestrict array trait implementations in the future (when const generics is stabilised). @Centril used the same approach to improve Many of the particularly common bugs with const generics have been fixed in the past few months. @nikomatsakis is investigating lazy normalisation, which should fix a host of the remaining issues, while @jplatte is looking into fixing the disambiguation of const parameters from type parameters (so you'll no longer have to type I also want to thank @eddyb for all their mentoring and reviewing for const generics throughout development, which has been invaluable. There are still quite a number of other issues to address and, as before, we could use all the help we can get — if you're interested in tackling any of the remaining issues, feel free to ping me on the issue, or on Discord or Zulip for pointers on getting started. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I would like to request that we reserve the discussion of such a significant syntactic change for either a thread on internals or an issue (or amending PR) on the RFCs repo. This issue's comment section is already quite long and the syntax in question seems unnecessary for a usable MVP of const generics. |
If we could move comments we probably would. We might want to lock the issue to @rust-lang team members and hide all the offtopic comments? All design discussion should happen on the RFC repo and all bug reports should be in separate issues. cc @rust-lang/moderation Is there precedent for doing this? |
You can convert a comment to an issue, but not move comments. Locking is fine, and i'd just hide off topic comments. |
With the start of the new year, I thought it would be good to give another update on where we are now with const generics. It's been a little over 2 years since the const generics RFC was accepted. In the first year (roughly 2018), a series of large refactoring efforts were undertaken to facilitate const generics by improving the handling of generic parameters generally throughout the compiler. In the second year (roughly 2019), work began on implementing const generics itself: first by getting the bare minimum working, and then by slowing improving the integrity of the feature. People also started to experiment with using const generics in the compiler itself. More detailed descriptions of these efforts are in the first two update posts: [1], [2]. There's been good progress in the last couple of months since the last update.
A big thanks to everyone who has been helping out with const generics! What's next? The biggest blocker for const generics at the moment is lazy normalisation, which is required for certain kinds of const generic bounds (such as in arrays). @Skinny121 is currently investigating lazy normalisation, continuing their fantastic efforts taking down the big bugs in const generics. This would address many of the present issues with const generics. Lazy normalisation aside, there are still a sizeable number of bugs and papercuts we'd like to address. If you're interested in tackling any of the remaining issues, feel free to ping me on the issue, or on Discord or Zulip for pointers on getting started. I'm confident we can make good headway in 2020 and hopefully approach a point where stabilisation becomes a viable discussion! |
Is there a subset of const generics that doesn't hit lazy normalization and doesn't have many bugs and papercuts, but which can express a good amount of useful code? I notice that std's impls of many traits for arrays seem to work just fine. Maybe there's a narrowing that would allow other crates to write the kind of impls we have in std for their own traits, even though they don't support all the fancier functionality? |
Now that we're looking to stabilize I want to use this comment to especially highlight and thank @varkor! They not only fixed some large and complicated issues but also do a lot of less visible work by mentoring and helping others as well as collecting and triaging the remaining issues. While so many amazing people are responsible for where we are now, I do not believe this would have been possible without @varkor. On other news, with #74060 now being merged, many traits are now implemented for arrays of any size, greatly improving the experience of working with them. This is available on stable since version 1.47 🎉
While they have not opened any pull requests themselves since the last update, I also want to thank @petrochenkov, @nikomatsakis and @oli-obk for reviewing and helping with many of the more complicated changes seen above. While we have come a long way over the last 3 years, this is still far from over. Even just for |
Thanks to @lcnr for the ongoing excellent summaries! |
All remaining const generics features are tracked in separate issues:
For more than 2 years now this issue has been pretty much exclusively used for update posts by either @varkor or myself. I intend to keep posting these updates but don't think this issue is necessarily the right place for them. I currently intend to post them to the Inside Rust blog, but I will try to link to the first of these posts here once the time has come. Once again a huge thanks to everyone who has contributed to const generics over the last 5 years. |
Tracking issue for rust-lang/rfcs#2000
Updates:
If you want to help out, take a look at the open const generics issues and feel free to ping @varkor, @eddyb, @yodaldevoid, @oli-obk or @lcnr for help in getting started!
Blocking stabilization:
Remaining implementation issues:
FIXME(const_generics)
comments.FIXME(const_generics_defaults)
).has_infer_types
.{X * 2}
.The text was updated successfully, but these errors were encountered: