-
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
stabilize #![feature(min_const_generics)]
in 1.51
#79135
stabilize #![feature(min_const_generics)]
in 1.51
#79135
Conversation
8f0d7b4
to
504ac2e
Compare
This comment has been minimized.
This comment has been minimized.
I don't even have enough words to say thank you to everyone that worked on this... |
@bors try |
⌛ Trying commit 504ac2eda6435080272e911f9822198c9b915229 with merge 90c27759f26e0dee460c146b45d69b36d2943c22... |
☀️ Try build successful - checks-actions |
Let's start with the crater run. @craterbot check |
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementation looks fine, so this can be merged after a FCP (which is blocked on a crater run).
It could be not a right place to ask this question, but I haven't seen it discussed in github issues. As I understand from #68436, the team is currently leaning towards making well-formedness bounds mandatory, at least for initial versions of const generics. But the example provided in the OP contains the following code: trait Foo<const N: usize> {
fn method<const M: usize>(&mut self, arr: [[u8; M]; N]);
}
struct Bar<T, const N: usize> {
inner: [T; N],
} It is obvious that using In the linked issue @oli-obk has wrote:
But with use generic_array::{GenericArray, ArrayLength};
pub struct Bar<N: ArrayLength<u8>> {
inner: GenericArray<u8, N>,
} Having exceptions for mandatory bounds looks like an incoherency to me. I think that either well-formedness bounds must be mandatory for all const expressions (including simple constants) used in type construction, or that they should not be mandatory in the first place as argued by me in the linked issue, since any CTFE panic (e.g. underflow and overflow errors) will result in a compilation error either way and the "too big" errors can appear in code which uses standalone const parameters. |
You are right, that clashes with what is stated in #68436, but we have opted to make an exception for arrays that are too big for the platform long ago. As you can see in https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=3b64dfe7c917d8016e5ca089cb03ad37, which in some form compiles since 1.0 up to the point where it recognizes that the array size is too large and aborts compilation. What we'll allow you to do at some point is to specify via a Also, note that So, my summary is basically that this is nothing new and this PR does not make the situation worse, even if easier to trigger. I reopened #25116 to track the bad diagnostics of this situation. |
I agree with this position. I had a different impression because in the #68436 discussion I've assumed that mandatory bounds will catch the "too big" error as well and no one has corrected me. To prevent adding noise to this PR, I will try to argue my position in #76560 a bit later. |
Remove `min_const_generics` feature Depends on rust-lang/rust#79135. If #240 is already under development and will be available before the 1.50 release, then feel free to close this PR. Otherwise, the feature removal will benefit upstream projects in the meanwhile.
Tracking issue: rust-lang#65798 This is unblocked now that `min_const_generics` has been stabilized in rust-lang#79135. This PR does *not* include the corresponding `IntoIterator` impl, which is rust-lang#65819. Instead, an iterator can be constructed through the `new` method. `new` would become unnecessary when `IntoIterator` is implemented and might be deprecated then, although it will stay stable.
2334: update rust january 7 2021 r=bradjc a=hudson-ayers ### Pull Request Overview This pull request updates the rust nightly version to 2021-01-07. This was motivated by the stabilization of `min_const_generics` ( rust-lang/rust#79135 ) -- by using this nightly, we will be able to use const generics in Tock without adding an unstable feature. ### Testing Strategy compiling ### TODO or Help Wanted N/A ### Documentation Updated - [x] Updated the relevant files in `/docs`. ### Formatting - [x] Ran `make prepush`. Co-authored-by: Hudson Ayers <[email protected]>
Remove `#![feature(const_generics)]` and `#![allow(incomplete_features)]` `#![feature(min_const_generics)]` has been [stabilized](rust-lang/rust#79135), so I removed `#![feature(const_generics)]` and `#![allow(incomplete_features)]` (I assume Miri is not built by the beta bootstrap compiler so it's fine to just remove them). The test [`tests/run-pass/specialization.rs` also has a `#![allow(incomplete_features)]` for `#![feature(specialization)]`](https://github.com/rust-lang/miri/blob/9949d9e4/tests/run-pass/specialization.rs#L1-L2). I think that can be removed and `#![feature(specialization)]` can be replaced with `#![feature(min_specialization)]`, but I'm not sure whether I should do that because it's a test. Feel free to ask me to remove it if it's fine to do so.
205: Generalizing gradients and add constant gradients r=Ogeon a=NicolasKlenert This pull request contains two commits: ### 1. Generalization of `Gradient` This allows creation of gradients from arrays. The inner collection type only has to be `ArrayLike`. For backward compatibility the default is still vector. This allows constant gradients and should also allow gradients to be supported for the next `#[no-std]` build. Other options to enable `#[no-std]` for gradients were briefly disscused in #156. ### 2. Adding some constant gradients This commit adds constant gradients. To be precise, it adds all 4 new matplotlib color gradients, which are perfectly perceptually-uniform, both in regular form and also when converted to black-and-white and therefore one of the most useful gradients. These are build the same way the named colors are built. A new feature-flag `named_gradients` is added to toggle said constants. This closes #62. ### Alterantives - The generalization of gradients can be achieved in a multiple of ways. Using a trait is just one of them and may be the wrong way to go. - However I think because this pull request doesn't have any breaking changes and gradients should be supporting arrays in future versions of the crate, it doesn't seem like this update of `Gradient` will cause more breaking API changes in the future than otherwise. Also constant gradients may be the only interaction with gradients a user needs, such that introducing them could reduce the number of users which actually relies on the generation of `Gradient` itself. - At the moment the 4 constant gradients are using linear interpolation but in nature these gradients are Spline-Interpolations of exaclty two points (and 2 controlpoints). If `Gradient` will support Spline-Inerpolation in the future and the exact controlpoints of these gradients can be found (I only found the colormaps), the gradients could be implemented more memory efficient. ### Remark These commits depend on const generics, which is a feature in beta but is planned to be stable on 2021-03-25 onwords (see [#79135](rust-lang/rust#79135)). Co-authored-by: Nicolas Klenert <[email protected]> Co-authored-by: NicolasKlenert <[email protected]> Co-authored-by: NicolasKlenert <[email protected]>
Pkgsrc changes: * Remove one SunOS patch, apparently no longer needed. * Adapt one patch for Darwin, adjust cargo checksum accordingly. * Adjust bootstraps to version 1.50.0. Version 1.51.0 (2021-03-25) ============================ Language -------- - [You can now parameterize items such as functions, traits, and `struct`s by constant values in addition to by types and lifetimes.][79135] Also known as "const generics" E.g. you can now write the following. Note: Only values of primitive integers, `bool`, or `char` types are currently permitted. ```rust struct GenericArray<T, const LENGTH: usize> { inner: [T; LENGTH] } impl<T, const LENGTH: usize> GenericArray<T, LENGTH> { const fn last(&self) -> Option<&T> { if LENGTH == 0 { None } else { Some(&self.inner[LENGTH - 1]) } } } ``` Compiler -------- - [Added the `-Csplit-debuginfo` codegen option for macOS platforms.][79570] This option controls whether debug information is split across multiple files or packed into a single file. **Note** This option is unstable on other platforms. - [Added tier 3\* support for `aarch64_be-unknown-linux-gnu`, `aarch64-unknown-linux-gnu_ilp32`, and `aarch64_be-unknown-linux-gnu_ilp32` targets.][81455] - [Added tier 3 support for `i386-unknown-linux-gnu` and `i486-unknown-linux-gnu` targets.][80662] - [The `target-cpu=native` option will now detect individual features of CPUs.][80749] - [Rust now uses `inline-asm` for stack probes when used with LLVM 11.0.1+][77885] \* Refer to Rust's [platform support page][forge-platform-support] for more information on Rust's tiered platform support. Libraries --------- - [`Box::downcast` is now also implemented for any `dyn Any + Send + Sync` object.][80945] - [`str` now implements `AsMut<str>`.][80279] - [`u64` and `u128` now implement `From<char>`.][79502] - [`Error` is now implemented for `&T` where `T` implements `Error`.][75180] - [`Poll::{map_ok, map_err}` are now implemented for `Poll<Option<Result<T, E>>>`.][80968] - [`unsigned_abs` is now implemented for all signed integer types.][80959] - [`io::Empty` now implements `io::Seek`.][78044] - [`rc::Weak<T>` and `sync::Weak<T>`'s methods such as `as_ptr` are now implemented for `T: ?Sized` types.][80764] Stabilized APIs --------------- - [`Arc::decrement_strong_count`] - [`Arc::increment_strong_count`] - [`Once::call_once_force`] - [`Peekable::next_if_eq`] - [`Peekable::next_if`] - [`Seek::stream_position`] - [`array::IntoIter`] - [`panic::panic_any`] - [`ptr::addr_of!`] - [`ptr::addr_of_mut!`] - [`slice::fill_with`] - [`slice::split_inclusive_mut`] - [`slice::split_inclusive`] - [`slice::strip_prefix`] - [`slice::strip_suffix`] - [`str::split_inclusive`] - [`sync::OnceState`] - [`task::Wake`] Cargo ----- - [Added the `split-debuginfo` profile option to control the -Csplit-debuginfo codegen option.][cargo/9112] - [Added the `resolver` field to `Cargo.toml` to enable the new feature resolver and CLI option behavior.][cargo/8997] Version 2 of the feature resolver will try to avoid unifying features of dependencies where that unification could be unwanted. Such as using the same dependency with a `std` feature in a build scripts and proc-macros, while using the `no-std` feature in the final binary. See the [Cargo book documentation][[email protected]] for more information on the feature. Rustdoc ------- - [Rustdoc will now include documentation for methods available from `Deref` traits.][80653] - [You can now provide a `--default-theme` flag which sets the default theme to use for documentation.][79642] Various improvements to intra-doc links: - [You can link to non-path primitives such as `slice`.][80181] - [You can link to associated items.][74489] - [You can now include generic parameters when linking to items, like `Vec<T>`.][76934] Misc ---- - [You can now pass `--include-ignored` to tests (e.g. with `cargo test -- --include-ignored`) to include testing tests marked `#[ignore]`.][80053] Compatibility Notes ------------------- - [WASI platforms no longer use the `wasm-bindgen` ABI, and instead use the wasm32 ABI.][79998] - [`rustc` no longer promotes division, modulo and indexing operations to `const` that could fail.][80579] - [The minimum version of glibc for the following platforms has been bumped to version 2.31 for the distributed artifacts.][81521] - `armv5te-unknown-linux-gnueabi` - `sparc64-unknown-linux-gnu` - `thumbv7neon-unknown-linux-gnueabihf` - `armv7-unknown-linux-gnueabi` - `x86_64-unknown-linux-gnux32` Internal Only ------------- - [Consistently avoid constructing optimized MIR when not doing codegen][80718] [79135]: rust-lang/rust#79135 [74489]: rust-lang/rust#74489 [76934]: rust-lang/rust#76934 [79570]: rust-lang/rust#79570 [80181]: rust-lang/rust#80181 [79642]: rust-lang/rust#79642 [80945]: rust-lang/rust#80945 [80279]: rust-lang/rust#80279 [80053]: rust-lang/rust#80053 [79502]: rust-lang/rust#79502 [75180]: rust-lang/rust#75180 [79135]: rust-lang/rust#79135 [81521]: rust-lang/rust#81521 [80968]: rust-lang/rust#80968 [80959]: rust-lang/rust#80959 [80718]: rust-lang/rust#80718 [80653]: rust-lang/rust#80653 [80579]: rust-lang/rust#80579 [79998]: rust-lang/rust#79998 [78044]: rust-lang/rust#78044 [81455]: rust-lang/rust#81455 [80764]: rust-lang/rust#80764 [80749]: rust-lang/rust#80749 [80662]: rust-lang/rust#80662 [77885]: rust-lang/rust#77885 [cargo/8997]: rust-lang/cargo#8997 [cargo/9112]: rust-lang/cargo#9112 [[email protected]]: https://doc.rust-lang.org/nightly/cargo/reference/features.html#feature-resolver-version-2 [`Once::call_once_force`]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.call_once_force [`sync::OnceState`]: https://doc.rust-lang.org/stable/std/sync/struct.OnceState.html [`panic::panic_any`]: https://doc.rust-lang.org/stable/std/panic/fn.panic_any.html [`slice::strip_prefix`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.strip_prefix [`slice::strip_suffix`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.strip_prefix [`Arc::increment_strong_count`]: https://doc.rust-lang.org/nightly/std/sync/struct.Arc.html#method.increment_strong_count [`Arc::decrement_strong_count`]: https://doc.rust-lang.org/nightly/std/sync/struct.Arc.html#method.decrement_strong_count [`slice::fill_with`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.fill_with [`ptr::addr_of!`]: https://doc.rust-lang.org/nightly/std/ptr/macro.addr_of.html [`ptr::addr_of_mut!`]: https://doc.rust-lang.org/nightly/std/ptr/macro.addr_of_mut.html [`array::IntoIter`]: https://doc.rust-lang.org/nightly/std/array/struct.IntoIter.html [`slice::split_inclusive`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_inclusive [`slice::split_inclusive_mut`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_inclusive_mut [`str::split_inclusive`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.split_inclusive [`task::Wake`]: https://doc.rust-lang.org/nightly/std/task/trait.Wake.html [`Seek::stream_position`]: https://doc.rust-lang.org/nightly/std/io/trait.Seek.html#method.stream_position [`Peekable::next_if`]: https://doc.rust-lang.org/nightly/std/iter/struct.Peekable.html#method.next_if [`Peekable::next_if_eq`]: https://doc.rust-lang.org/nightly/std/iter/struct.Peekable.html#method.next_if_eq
Pkgsrc changes: * Add support for the big-endian arm64 NetBSD target (aarch64_be). * On NetBSD/i386, use the i586 (pentium) bootstrap kit variant in preference to i686. * Adjust patches, re-compute line offsets, re-compute crate checksums. * Remove a patch which was either integrated upstream and/or no longer applies. * Bump bootstraps to 1.50.0. * Move conditionals until after bsd.prefs.mk so that they work... * Default to "dist" build target if cross-compiling, but allow also to override via rust.BUILD_TARGET. * Allow overriding MAKE_JOBS_SAFE via rust.MAKE_JOBS_SAFE if you want a different trade-off between occasional breakage and performance. * Adjust platform.mk according to work already done in wip/rust/ * Add a patch to optimize the install.sh script used to install binary bootstraps to not do so many forks; use case/esac and parameter expansion instead of grep, sed and cut. * Drop building documentation for the binary bootstrap kits. This will also impact the lang/rust-bin package. For full documentation, build or install lang/rust as a package. Upstream changes: Version 1.51.0 (2021-03-25) ============================ Language -------- - [You can now parameterize items such as functions, traits, and `struct`s by constant values in addition to by types and lifetimes.][79135] Also known as "const generics" E.g. you can now write the following. Note: Only values of primitive integers, `bool`, or `char` types are currently permitted. ```rust struct GenericArray<T, const LENGTH: usize> { inner: [T; LENGTH] } impl<T, const LENGTH: usize> GenericArray<T, LENGTH> { const fn last(&self) -> Option<&T> { if LENGTH == 0 { None } else { Some(&self.inner[LENGTH - 1]) } } } ``` Compiler -------- - [Added the `-Csplit-debuginfo` codegen option for macOS platforms.][79570] This option controls whether debug information is split across multiple files or packed into a single file. **Note** This option is unstable on other platforms. - [Added tier 3\* support for `aarch64_be-unknown-linux-gnu`, `aarch64-unknown-linux-gnu_ilp32`, and `aarch64_be-unknown-linux-gnu_ilp32` targets.][81455] - [Added tier 3 support for `i386-unknown-linux-gnu` and `i486-unknown-linux-gnu` targets.][80662] - [The `target-cpu=native` option will now detect individual features of CPUs.][80749] \* Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. Libraries --------- - [`Box::downcast` is now also implemented for any `dyn Any + Send + Sync` object.][80945] - [`str` now implements `AsMut<str>`.][80279] - [`u64` and `u128` now implement `From<char>`.][79502] - [`Error` is now implemented for `&T` where `T` implements `Error`.][75180] - [`Poll::{map_ok, map_err}` are now implemented for `Poll<Option<Result<T,E>>>`.][80968] - [`unsigned_abs` is now implemented for all signed integer types.][80959] - [`io::Empty` now implements `io::Seek`.][78044] - [`rc::Weak<T>` and `sync::Weak<T>`'s methods such as `as_ptr` are now implemented for `T: ?Sized` types.][80764] - [`Div` and `Rem` by their `NonZero` variant is now implemented for all unsigned integers.][79134] Stabilized APIs --------------- - [`Arc::decrement_strong_count`] - [`Arc::increment_strong_count`] - [`Once::call_once_force`] - [`Peekable::next_if_eq`] - [`Peekable::next_if`] - [`Seek::stream_position`] - [`array::IntoIter`] - [`panic::panic_any`] - [`ptr::addr_of!`] - [`ptr::addr_of_mut!`] - [`slice::fill_with`] - [`slice::split_inclusive_mut`] - [`slice::split_inclusive`] - [`slice::strip_prefix`] - [`slice::strip_suffix`] - [`str::split_inclusive`] - [`sync::OnceState`] - [`task::Wake`] - [`VecDeque::range`] - [`VecDeque::range_mut`] Cargo ----- - [Added the `split-debuginfo` profile option to control the -Csplit-debuginfo codegen option.][cargo/9112] - [Added the `resolver` field to `Cargo.toml` to enable the new feature resolver and CLI option behavior.][cargo/8997] Version 2 of the feature resolver will try to avoid unifying features of dependencies where that unification could be unwanted. Such as using the same dependency with a `std` feature in a build scripts and proc-macros, while using the `no-std` feature in the final binary. See the [Cargo book documentation][[email protected]] for more information on the feature. Rustdoc ------- - [Rustdoc will now include documentation for methods available from _nested_ `Deref` traits.][80653] - [You can now provide a `--default-theme` flag which sets the default theme to use for documentation.][79642] Various improvements to intra-doc links: - [You can link to non-path primitives such as `slice`.][80181] - [You can link to associated items.][74489] - [You can now include generic parameters when linking to items, like `Vec<T>`.][76934] Misc ---- - [You can now pass `--include-ignored` to tests (e.g. with `cargo test -- --include-ignored`) to include testing tests marked `#[ignore]`.][80053] Compatibility Notes ------------------- - [WASI platforms no longer use the `wasm-bindgen` ABI, and instead use the wasm32 ABI.][79998] - [`rustc` no longer promotes division, modulo and indexing operations to `const` that could fail.][80579] - [The minimum version of glibc for the following platforms has been bumped to version 2.31 for the distributed artifacts.][81521] - `armv5te-unknown-linux-gnueabi` - `sparc64-unknown-linux-gnu` - `thumbv7neon-unknown-linux-gnueabihf` - `armv7-unknown-linux-gnueabi` - `x86_64-unknown-linux-gnux32` - [`atomic::spin_loop_hint` has been deprecated.][80966] It's recommended to use `hint::spin_loop` instead. Internal Only ------------- - [Consistently avoid constructing optimized MIR when not doing codegen][80718] [79135]: rust-lang/rust#79135 [74489]: rust-lang/rust#74489 [76934]: rust-lang/rust#76934 [79570]: rust-lang/rust#79570 [80181]: rust-lang/rust#80181 [79642]: rust-lang/rust#79642 [80945]: rust-lang/rust#80945 [80279]: rust-lang/rust#80279 [80053]: rust-lang/rust#80053 [79502]: rust-lang/rust#79502 [75180]: rust-lang/rust#75180 [79135]: rust-lang/rust#79135 [81521]: rust-lang/rust#81521 [80968]: rust-lang/rust#80968 [80959]: rust-lang/rust#80959 [80718]: rust-lang/rust#80718 [80653]: rust-lang/rust#80653 [80579]: rust-lang/rust#80579 [79998]: rust-lang/rust#79998 [78044]: rust-lang/rust#78044 [81455]: rust-lang/rust#81455 [80764]: rust-lang/rust#80764 [80749]: rust-lang/rust#80749 [80662]: rust-lang/rust#80662 [79134]: rust-lang/rust#79134 [80966]: rust-lang/rust#80966 [cargo/8997]: rust-lang/cargo#8997 [cargo/9112]: rust-lang/cargo#9112 [[email protected]]: https://doc.rust-lang.org/nightly/cargo/reference/features.html#feature-resolver-version-2 [`Once::call_once_force`]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.call_once_force [`sync::OnceState`]: https://doc.rust-lang.org/stable/std/sync/struct.OnceState.html [`panic::panic_any`]: https://doc.rust-lang.org/stable/std/panic/fn.panic_any.html [`slice::strip_prefix`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.strip_prefix [`slice::strip_suffix`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.strip_prefix [`Arc::increment_strong_count`]: https://doc.rust-lang.org/nightly/std/sync/struct.Arc.html#method.increment_strong_count [`Arc::decrement_strong_count`]: https://doc.rust-lang.org/nightly/std/sync/struct.Arc.html#method.decrement_strong_count [`slice::fill_with`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.fill_with [`ptr::addr_of!`]: https://doc.rust-lang.org/nightly/std/ptr/macro.addr_of.html [`ptr::addr_of_mut!`]: https://doc.rust-lang.org/nightly/std/ptr/macro.addr_of_mut.html [`array::IntoIter`]: https://doc.rust-lang.org/nightly/std/array/struct.IntoIter.html [`slice::split_inclusive`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_inclusive [`slice::split_inclusive_mut`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_inclusive_mut [`str::split_inclusive`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.split_inclusive [`task::Wake`]: https://doc.rust-lang.org/nightly/std/task/trait.Wake.html [`Seek::stream_position`]: https://doc.rust-lang.org/nightly/std/io/trait.Seek.html#method.stream_position [`Peekable::next_if`]: https://doc.rust-lang.org/nightly/std/iter/struct.Peekable.html#method.next_if [`Peekable::next_if_eq`]: https://doc.rust-lang.org/nightly/std/iter/struct.Peekable.html#method.next_if_eq [`VecDeque::range`]: https://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.range [`VecDeque::range_mut`]: https://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.range_mut
This was possible thanks to the [stabilisation of minimal const generics support](rust-lang/rust#79135) in Rust 1.51.
A new Kind
A Sort long Prophesized
Once Fragile, now Eternal
Stabilization report
This is the stabilization report for
#![feature(min_const_generics)]
(tracking issue #74878), a subset of#![feature(const_generics)]
(tracking issue #44580), based on rust-lang/rfcs#2000.The version target is
1.50 (2020-12-31 => beta, 2021-02-11 => stable)1.51 (2021-02-11 => beta, 2021-03-25 => stable).This report is a collaborative effort of @varkor, @shepmaster and @lcnr.
Summary
It is currently possible to parameterize functions, type aliases, types, traits and implementations by types and lifetimes.
With
#![feature(min_const_generics)]
, it becomes possible, in addition, to parameterize these by constants.This is done using the syntax
const IDENT: Type
in the parameter listing. Unlike full const generics,min_const_generics
is limited to parameterization by integers, and constants of typechar
orbool
.We already use
#![feature(min_const_generics)]
on stable to implement many common traits for arrays. See the documentation for specific examples.Generic const arguments, for now, are not permitted to involve computations depending on generic parameters. This means that const parameters may only be instantiated using either:
{ foo() + 1 }
, wherefoo
is aconst fn
{N}
Example
Motivation
Rust has the built-in array type, which is parametric over a constant. Without const generics, this type can be quite cumbersome to use as it is not possible to generically implement a trait for arrays of different lengths. For example, this meant that, for a long time, the standard library only contained trait implementations for arrays up to a length of 32. This restriction has since been lifted through the use of const generics.
Const parameters allow users to naturally specify variants of a generic type which are more naturally parameterized by values, rather than by types. For example, using const generics, many of the uses of the crate typenum may now be replaced with const parameters, improving compilation time as well as code readability and diagnostics.
The subset described by
min_const_generics
is self-contained, but extensive enough to help with the most frequent issues: implementing traits for arrays and using arbitrarily-sized arrays inside of other types. Furthermore, it extends naturally to fullconst_generics
once the remaining design and implementation questions have been resolved.In-depth feature description
Declaring const parameters
Const parameters are allowed in all places where types and lifetimes are supported. They use the syntax
const IDENT: Type
. Currently, const parameters must be declared after lifetime and type parameters. Their scope is equal to the scope of other generic parameters. They live in the value namespace.Type
must be one ofu8
,u16
,u32
,u64
,u128
,usize
,i8
,i16
,i32
,i64
,i128
,isize
,char
andbool
. This restriction is implemented in two places:The updated syntax of parameter listings is:
Unlike type and lifetime parameters, const parameters of types can be used without being mentioned inside of a parameterized type because const parameters do not have issues concerning variance. This means that the following types are allowed:
Const arguments
Const parameters are instantiated using const arguments. Any concrete const expression or const parameter as a standalone argument can be used. When applying an expression as const parameter, most expressions must be contained within a block, with two exceptions:
This syntactic restriction is necessary to avoid ambiguity, or requiring infinite lookahead when parsing an expression as a generic argument.
In the cases where a generic argument could be resolved as either a type or const argument, we always interpret it as a type. This causes the following test to fail:
To circumvent this, the user may wrap the const parameter with braces, at which point it is unambiguously accepted.
Operations depending on generic parameters are not allowed, which is enforced during well-formedness checking. Allowing generic unevaluated constants would require a way to check if they would always evaluate successfully to prevent errors that are not caught at declaration time. This ability forms part of
#![feature(const_evaluatable_checked)]
, which is not yet being stabilised.Since we are not yet stabilizing
#![feature(lazy_normalization_consts)]
, we must not supply the parent generics to anonymous constants except for repeat expressions. Doing so can cause cycle errors for arrays used inwhere
-bounds. Not supplying the parent generics can however lead to ICEs occurring before well-formedness checking when trying to use a generic parameter. See #56445 for details.Since we expect cases like this to occur more frequently once
min_const_generics
is stabilized, we have chosen to forbid generic parameters in anonymous constants during name resolution. While this changes the ICE in the situation above to an ordinary error, this is theoretically a breaking change, as early-bound lifetimes were previously permitted in repeat expressions but now are disallowed, causing the following snippet to break:Using const parameters
Const parameters can be used almost everywhere ordinary constants are allowed, except that they may not be used in the construction of consts, statics, functions, or types inside a function body and are subject to the generic argument restrictions mentioned above.
Expressions containing const parameters are eligible for promotion:
Symbol mangling
See the Rust symbol name mangling RFC for an overview. Generic const parameters take the form
K[type][value]
when the value is known, orKp
where the value is not known, where:[type]
is any integral type,bool
, orchar
.[value]
is the unsigned hex value for integers, preceded byn
when negative; is0
or1
forbool
; is the hex value forchar
.Exhaustiveness checking
We do not check the exhaustiveness of impls, meaning that the following example does not compile:
Type inference
The value of const parameters can be inferred during typeck. One interesting case is the length of generic arrays, which can also be inferred from patterns (implemented in #70562). Practical usage of this can be seen in #76825.
Equality of constants
#![feature(min_const_generics)]
only permits generic parameters to be used as standalone generic arguments. We compare two parameters to be equal if they are literally the same generic parameter.Associated constants
Associated constants can use const parameters without restriction, see #79135 (comment) for more details.
Future work
As this is a limited subset of rust-lang/rfcs#2000, there are quite a few extensions we will be looking into next.
Lazy normalization of constants
Stabilizing
#![feature(lazy_normalization_consts)]
(tracking issue #72219) will remove some special cases that are currently necessary formin_const_generics
, and unblocks operations on const parameters.Relaxing ordering requirements between const and type parameters
We currently restrict the order of generic parameters so that types must come before consts. We could relax this, as is currently done with
const_generics
. Without this it is not possible to use both type defaults and const parameters at the same time.Unrestricting the order will require us to improve some diagnostics that expect there to be a strict order between type and const parameters.
Allowing more parameter types
We would like to support const parameters of more types, especially
&str
and user-defined types. Both are blocked on valtrees. There are also open questions regarding the design ofstructural_match
concerning the latter. Supporting generic const parameter types such asstruct Foo<T, const N: T>
will be a lot harder and is unlikely to be implemented in the near future.Default values of const parameters
We do not yet support default values for const parameters. There is work in progress to enable this on nightly (see #75384).
Generic const operations
With
#![feature(min_const_generics)]
, only concrete const expressions and parameters as standalone arguments are allowed in types and repeat expressions. However, supporting generic const operations, such asN + 1
orstd::mem::size_of::<T>()
is highly desirable. This feature is in early development under#![feature(const_evaluatable_checked)]
.Implementation history
Many people have contributed to the design and implementation of const generics over the last three years. See #44580 (comment) for a summary. Once again thank you to everybody who helped out here!
r? @varkor