It's simply not intended by the language. The syntax and semantics of a language are very strict rules, which must be followed, so the compiler can tell sense out of your code.
The compiler was able to provide the ::<...> tip, because someone implemented a lint for it. Maybe because it is a general error done by newcomers.
The reason is that Vec<u64> looks very much like vec<v64, i.e. a comparison between variables vec and v64 that evaluates to a boolean value. The next > token could still be a comparison, because you can compare two boolean values, and unless I am mistaken, ::new() could be a namespaced function call.
@Cigaes, so I suppose the answer to my question is that, unlike C++, Rust wants to have a context-free grammar? So the interpretation of < as a comparison or an angle-bracket around type parameters, cannot depend on whether the name before it is a type or a variable? Makes sense.
But is that really fully context free? I mean, it still uses < and lets it mean different things, it's just a matter of "is it coming right after :: or not"? But maybe you're right: it's context free in that sense, that right after :: it always means the same thing... It still can mean different things, but is more strict than C++ and C#.
Yeah, context free is a misnomer: it has a technical sense of "amendable to parsing by a push-down automaton", and a common sense "you don't need to see the context to decide what the thing is". It happens than technically context free languages are actually "context-sensitive" in the common sense.
So technically, even Rust's lexical grammar is not context free. (Proof: the culprit is raw string literals, you can intersect them with a regular language and apply the pumping lemma). But if we treat tokens as symbols, then the syntactic grammar looks like context free (there are a couple of LALR style grammars out there, but as far as I know neither have been extensively compared with the canonical rustc parser).
In practice, Rust is relatively easy to parse by an LL-style parser, though there is some weirdness around semi-statement blockish expressions like ifs, while , match, etc, and there are surprising rules about struct literals in conditionals.
context free grammar
c++ is so difficult to parse because of and expression ambiguities (consider what can happen e.g. with expressions in type-params aswell..), it needs to resolve all symbols first.. this is a nightmare and constrains tooling
as a newcomer this behavior was confusing for me. is there a rust documentation explaining where :: is applicable and where it's unnecessary?
let _ = Vec<String>::new(); // error: use `::<...>` instead of `<...>` if you meant to specify type arguments
let _ = Vec::<String>::new(); // fix (note: compiler expects `::`)
let _: Vec::<String> = Vec::new(); // unnecessary path disambiguator; try removing `::`
let _: Vec<String> = Vec::new(); // fix (note: compiler does NOT expect `::`)
let _: Vec<String> = Vec::<String>::new(); // lhs and rhs have different expectations on `::`
"context-free" has a very specific technical, mathematical meaning in the theory of formal languages. Sure, in a human sense, the meaning of < depends on other "context", but technically, the grammar of Rust is (almost, I think) context-free in the sense that it's possible to unambiguously parse Rust code without having to maintain a symbol table or otherwise intermingle parsing and semantic analysis/type checking in the compiler. (Incidentally, it's exactly this property of context-free grammars that makes them so much nicer to work with when writing a compiler.)
To be concrete, this example (playground) shows the illegal syntax together with the two variations that do work:
#![allow(non_upper_case_globals)]
const Vec: u32 = 10;
const u32: u32 = 20;
fn new() -> bool { true }
fn main() {
let a = Vec::<u32>::new();
let b = (Vec < u32) > ::new();
// let c = Vec<u32>::new(); // does not compile
println!("a: {:?}", a);
println!("b: {:?}", b);
}
So a is a vector, and b is a Boolean. The third option doesn't compile, it requires you to pick one of the other syntaxes to be explicit about what you mean.