2 ms·
Rust very deliberately treats parsing as an isolated step in compilation. The ASTs of {function + type parameter + arguments} and {value + indexing + call} are
by chrismorgan 6y ago
Rust very deliberately treats parsing as an isolated step in compilation. The ASTs of {function + type parameter + arguments} and {value + indexing + call} are very different. At parse time, you don’t know what types and values are in scope—they’re resolved later.
Some languages have been willing to compromise on this (C and C++ certainly do, and Perl is famously unparseable), but it always causes a great deal of pain, as you can’t build any sort of isolated tooling around the language any more, but must use an actual compiler to even try to parse the thing properly if you want to be robust; static analysis is thus made more difficult, especially as you must now look at entire projects and can’t properly look at individual files—and worse, you must be able to compile the project to be able to analyse it.
So Rust has deliberately gone the other way: you can parse the language easily and completely, so any form of static analysis doesn’t need a real compiler to back it and can act on files in isolation.
In short, Rust is philosophically obdurately opposed to needing to do disambiguation in the parsing phase.
So it’s actually not really about the actual ambiguity, which might not even be a thing—I can’t remember whether {function + type parameter} would be looking up in the type or value namespaces, so my example might actually be wrong there—but rather that you can devise supporting code that would seem to make `a[b](c)` mean two different things, and that’s untenable for Rust, because it refuses to let scope contents influence the parse.
- edflsafoiewq 6y agoI don't really understand why the ASTs need to be different. That is I don't really see why it's so different from fn a<T>(_: T) -> i32 { 0 } fn main() { let a = |_: i32| 1; let c = 0; a(c); } except that a[b](c) requires that an expression can be a type.
- chrismorgan 6y agoAs I say, the particular example I used may not properly demonstrate the precise ambiguity after all (not certain), but the fact stands that Rust is unwilling to put something in its AST that might be a type or an expression. You must know at parse time whether it’s to be taken as a type or an expression. And semantically they’re quite different, as is always the case with types versus values: one is a function call with generic type parameters, which are resolved at compile time, while the other is doing indexing at run time, and then calling it. For them to have the same AST, even were it possible, would be making the AST hollow.