Flashcard Rust: Colon colon angle bracket or turbofish!

A Rust flashcard explaining turbofish syntax, why type inference sometimes needs help, and two ways to provide a concrete type.
coding
rust
Author

unrahul

Published

January 17, 2021

This confused me a lot when I started learning Rust. “Colon colon angle bracket” is what I searched for first because I had no idea the syntax had a name. It does: turbofish.

Flashcard 05 Rust

The question

What does ::<T> tell the Rust compiler?

Think about what parse knows before the result has a concrete type.

Reveal the answer

It supplies a concrete generic type when Rust cannot infer one from the surrounding code.

Where I hit it

I had a string containing pi and wanted to parse it into a number:

fn main() {
    let pi_string = "3.1415";
    let pi_float = pi_string.parse().unwrap();
    println!("{}", pi_float);
}

It looks reasonable, but parse can produce many different types. At this point Rust has no way to know whether I want an f32, an f64, or something else.

error[E0284]: type annotations needed
 --> src/main.rs:3:9
  |
3 |     let pi_float = pi_string.parse().unwrap();
  |         ^^^^^^^^ consider giving `pi_float` a type

What the compiler is asking for

The call to parse is generic. I need to provide the missing concrete type either on the function call or on the variable receiving the result.

Fix it with the turbofish

The ::<f32> after parse gives the compiler the type directly:

fn main() {
    let pi_string = "3.1415";
    let pi_float = pi_string.parse::<f32>().unwrap();
    println!("{}", pi_float);
}
3.1415

Or use a type annotation

The same information can come from the variable:

fn main() {
    let pi_string = "3.1415";
    let pi_float: f32 = pi_string.parse().unwrap();
    println!("{}", pi_float);
}

Both versions compile. I tend to use the form that makes the type easiest to see where I am reading the code.

What I keep in my head

::<T> fills in a generic type explicitly. With parse::<f32>(), the f32 is the concrete type that Rust could not infer on its own.