Hacker News new | ask | show | jobs
by twic 2227 days ago
The planned const generics syntax is going to look pretty weird, because it builds on type generics. If Rust had chosen a different syntax for type generics, const generics might look less weird.

The futures design was built with epoll in mind, and now people are trying to wrap it round io_uring, they are feeling some pain. Would a different design have worked better, without massive drawbacks?

1 comments

> The planned const generics syntax is going to look pretty weird, because it builds on type generics. If Rust had chosen a different syntax for type generics, const generics might look less weird.

Could you provide an example? Because I don't really see it, except by requiring that non-const generics also be explicitly annotated?

I'm thinking of the need to have blocks wrapping expressions in types [1]:

  const X: usize = 7;
  
  let x: RectangularArray<i32, 2, 4>;
  let y: RectangularArray<i32, X, {2 * 2}>;
Simple cases are fine, but i suspect a lot of real-world use of const generics are going to require blocks.

AIUI, this is only because <> was chosen as the container for type arguments, and > is also a legal operator in expressions. So, for example, if Rust had used Scala-esque [] for type arguments, this would not be a problem.

[1] https://rust-lang.github.io/rfcs/2000-const-generics.html#ap...

While I would prefer brackets, that would not be enought to solve all the problems since, there would be conflict with array syntax too.
But the square brackets used in array access nest, so the parsing is never ambiguous.

The reason > needs braces is that without them, if you're parsing and so far you've seen these characters:

  let y: RectangularArray<i32, X, 2>
You don't know if that final > is ending the argument list, or is a greater-than operator, with the rest of an expression coming after it.

But if it was square brackets, then a closing square bracket on its own can only ever be the end of the list:

  let y: RectangularArray[i32, X, 2]
Because if it was closing an array access, there would have to have been an opening square bracket:

  let y: RectangularArray[i32, X, a[1]
In case anyone ever stumbles across this thread, a couple of posts about this:

https://keleshev.com/parsing-ambiguity-type-argument-v-less-...

https://soc.me/languages/stop-using-for-generics

That's what I originally thought about, but the thing is `]` in and of itself is not an operator while `>` is, so

    foo<bar, qux>corge>
"is" valid syntax while

    foo[bar, qux]corge]
is not. The former requires some sort of disambiguation, while the latter is not. Put an other way, in terms of syntax `[]` always parses the same way (with `[` is infix and `]` terminates it), there can be ambiguity between indexing and generics but it doesn't really matter for the original parsing.

For `<>` however, the parsing itself can be ambiguous as `>` could either be the terminator of an earlier `<` or it could be the infix `>` operator. That is where the issue lies, you can't know how to build the AST without either explicit disambiguation, or infinite lookaheads.