Why :: before generic type <T> when calling a function?

This is a pure syntax question.

If we have a function, e.g.:

fn f<T>() {...}

When calling the function, we need to write:

f::<T>()

This seems “syntactically inconsistent”. Are there any reasons we need to add the “::”?

We also have:

Vec::<i32>::new()

and

let v: Vec<i32> = ...

together, in the case of struct with generic types.

This bothers me a little bit. Why not go “always no :: before generic types”? Are there any fundamental reasons stopping us doing that?

This is called turbofish, and it exists to avoid ambiguity in syntax. f<T>() could be parsed as (f < T) > ()f less than T, and that result greater than the unit (). That’s nonsense at the type level, but could be valid syntax. Or in a language with chained comparisons (like Python), it could be parsed as the equivalent of (f < T) && (T > ()).

There are more examples in RFC 2544, which aims to make turbofish optional after all.

5 Likes

Thanks for the reply! It makes sense, and the turbofish website looks cool!

Note that the difference here is type context vs expression context – you can also write

let mut v = <Vec<i32>>::new();

without the :: because the extra < tells the parser that a type is coming.

6 Likes

Thanks! Learned.