4 ms·
Rust will also support it one day, as part of the const generics feature. Partial support is there behind a feature flag. https://play.rust-lang.org/?version=n
by Arnavion 7y ago
Rust will also support it one day, as part of the const generics feature. Partial support is there behind a feature flag.
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=7cf04999dd6d093fc34da5c022a04b8f https://play.rust-lang.org/?version=nightly&mode=debug&editi...
#![feature(const_generics)]
#[derive(PartialEq, Eq)] // enums used as const generics must be Eq
enum Color { Green, Yellow, Red }
struct State<const COLOR: Color>;
impl State<{ Color::Green }> { fn next(self) -> State<{ Color::Yellow }> { State } }
impl std::fmt::Debug for State<{ Color::Green }> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str("green") } }
impl State<{ Color::Yellow }> { fn next(self) -> State<{ Color::Red }> { State } }
impl std::fmt::Debug for State<{ Color::Yellow }> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str("yellow") } }
impl State<{ Color::Red }> { fn next(self) -> State<{ Color::Green }> { State } }
impl std::fmt::Debug for State<{ Color::Red }> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str("red") } }
impl State<{ Color::Green }> { fn new() -> Self { State } }
fn main() {
let state = dbg!(State::<{ Color::Green }>::new());
let state = dbg!(state.next());
let state = dbg!(state.next());
let state = dbg!(state.next());
}
Output:
[src/main.rs:20] State::<{ Color::Green }>::new() = green
[src/main.rs:21] state.next() = yellow
[src/main.rs:22] state.next() = red
[src/main.rs:23] state.next() = green
- DougBTX 7y agoAre the braces around the const expressions planned to be optional in future? I'm wondering if this will work: impl State<Color::Green> { fn next(self) -> State<Color::Yellow> { ... } }
- Arnavion 7y agoI believe they're intentional, to disambiguate from `mod Color { struct Green; }`, and because they can be arbitrarily complex expressions.
- grenoire 7y agoCurrently the compiler gives "not a type" when the brackets are removed; I agree that it might be to disambiguate, but it's confusing and redundant syntax. I expect { } to be used strictly for blocks in Rust.
- hobofan 7y agoIt's a block though, isn't it? Color::Green is an enum variant while { Color::Green } is a (constant) block (expression) that evaluates to an instance which is used as a generic type parameter. The difference might be more easily understandable if we look at an enum variant that holds a value, where the syntactic differences between variant and instance constructor are more clearly visible. Color::RGB(u64, u64, u64) vs { Color::RGB(10, 20, 30) }
- DougBTX 7y agoHm, the RFC says the braces are needed if it is not an "identity expression" with the examples: const X: usize = 7; let x: RectangularArray<i32, 2, 4>; let y: RectangularArray<i32, X, {2 * 2}>; So I'm still not sure if Color::Green is an identity expression, they say: > Identity expression: An expression which cannot be evaluated further except by substituting it with names in scope. This includes all literals as well all idents So... maybe? Depends on whether Color::Green is an ident or not. At the very least I'd expect this to work, but it doesn't yet: use Color::*; impl State<Green> { ... }
- fluffything 7y agoA name in scope is a path to a name, and Color::Green is also a path, so if impl<Green> works impl<Color::Green> would work as well.
- fluffything 7y agoC++ requires using the template keyword to disambiguate, i.e., one has to write `foo.template bar<22>()` as opposed to `foo.bar<22>()` (did you mean `(foo.bar < 2*2) > ()` ?). The main reason Rust meta-programming is so much better than D and C++ is that Rust has an LL(k) grammar that's trivial to parse into ASTs that can be easily manipulated. That feature alone is definitely worth the annoyance of having to use an editor that types `{}` for you when inputting a constant expression. It's the same with removing the `::` in `::<>` - can be done, but the costs are not worth the ergonomic improvement. That is, I don't think the claim that the braces are redundant is correct - they are there for a reason: to keep a simple grammar, which happens to be one of the most important Rust features that everybody uses every day (every single proc macro uses this feature, that includes the `println!` in `println!("Hello World")` Rust examples).
- estebank 7y agoThat is the long term plan. In the meantime we also have intentions of making rustc interpret what you want even when the grammar would require the disambiguation so that it can provide the appropriate suggestion in that case. https://github.com/rust-lang/rust/pull/64700 https://github.com/rust-lang/rust/pull/64700