Where to put the turbofish

In a case that you need to specify the concrete type for a generic function, method, struct, or enum, rust has this special syntax that's called the turbofish. The rule of thumb is, whenever you see:

$ident<T>

in any kind of definition, then in an expression context you usually need to write:

$ident::<T>

to specify the type for the generic parameter. Here a few examples of common usage of this syntax. Divided into four sections.

Generic Function

The std::mem::size_of() has this signature:

pub fn size_of<T>() -> usize

Writing, for example:

std::mem::size_of::<u8>()

Will tell you what's the size of u8 in bytes. It's kind of amazing that you can use generic in this way.

Generic Method

The parse() method for str is also one of the few times that you'll see the turbofish syntax being used. It's signature is:

fn parse<F>(&self) -> Result<F, F::Err> where F: FromStr

We can use the turbofish to tell the desired type that should be parsed from the str

"2048".parse::<u32>()

Another common example is collect() on Iterator. It's type signature:

fn collect<B>(self) -> B where B: FromIterator<Self::Item>

Because the compiler already know the type of Self::Item you're collecting, we usually didn't need to specify it. Instead we can write _ to let the compiler infer it automaticallly. For example, collecting into a Vec<u8> from Iterator<Item=u8>can be written as:

[1u8, 2, 3, 4].iter().collect::<Vec<_>>()

And speaking of Iterator, you also probably forced to use the turbofish syntax when using sum() and product() method on it. Here the signature for those method:

fn sum<S>(self) -> S where S: Sum<Self::Item>
fn product<P>(self) -> P where P: Product<Self::Item>

The sum and product of the first four positive integers can be calculated as:

[1, 2, 3, 4].iter().sum::<u32>()
[1, 2, 3, 4].iter().product::<u32>()

Generic Struct

In case of the compiler can't infer enough information when creating a generic struct, you can also use the turbofish syntax. For example, Vec was defined as:

pub struct Vec<T> { /* fields omitted */ }

To use the turbofish syntax, for example when creating a new Vec with Vec::new(), you can write it as:

Vec::<u8>::new()

Take a note that we put the turbofish after the Vec, not the new method. Since the ones that generic is the struct, not the method. Bear with me for this one, since it's still follow the rule of thumb above.

And yes, you can do this to all rust collections. See HashSet for another example. Below we create a new HashSet with 10 capacity.

std::collections::HashSet::<u8>::with_capacity(10)

And the HashSet signature itself:

pub struct HashSet<T, S = RandomState> { /* fields omitted */ }

Still, it all follows the rule of thumb above.

Generic Enum

This is ones that didn't follow our rule of thumb. Historically speaking, enum in rust isn't scoped by their enum type, hence, we put the turbofish after the enum variant, not after their type. To make it clear let's see how we use turbofish for Result which is an enum defined as:

#[must_use]
pub enum Result<T, E> {
    Ok(T),
    Err(E),
}

We use it like this

Result::Ok::<u8, ()>(10)
Result::Err::<u8, ()>(())

See that we put the turbofish after Ok and Err, the variant, not after the Result type itself. And also, since that variant was available in prelude, actually we can just write it as follow:

Ok::<u8, ()>(10)
Err::<u8, ()>(())

The same also applies to Option. Which also just an enum defined as:

pub enum Option<T> {
    None,
    Some(T),
}

Unwrapping a None value, for example, can be written as:

None::<u8>.unwrap()

Closing

It's a nice thing to have this syntax, but remember, you can always bind the value to a variable using the let syntax and declare the type explicitly. For an alternative, there's also a feature in nightly that combine the best of those two world. See the type ascription tracking issue for details.

Reference