Rust's Turbofish (`::<>`): When the Compiler Needs Help
The turbofish (`::<>`) is your tool to resolve ambiguity when Rust's compiler can't infer a type or trait. Use it when a type implements multiple traits with same-named methods, forcing the compiler to pick the one you specify.
WHY IT EXISTS: Rust allows a type to implement multiple traits, and those traits can have methods with the same name. This creates ambiguity. Without a way for the programmer to specify which method they mean, the compiler would have to reject the code. Fully qualified syntax exists to resolve this ambiguity by providing an explicit path.
THE MENTAL MODEL: Think of the turbofish (::<>) and its related syntax as giving the compiler a full, unambiguous path to a function, like using /usr/bin/python instead of just python. When your shell's PATH has multiple conflicting executables, you must be specific. This syntax is you being specific to the Rust compiler.
HOW IT WORKS: The syntax <Type as Trait>::method(...) is called "fully qualified syntax". It instructs the compiler to bypass its normal method lookup process. Instead of searching for any method that can be called on Type, it directly uses the method implementation from the Trait block for that Type. A related form, my_iterator.collect::<Vec<u8>>(), is used to provide type hints for generic functions and is where the "turbofish" nickname for ::<> originates.
WHEN TO USE IT: Use it when the compiler gives an error about "multiple applicable items" or an ambiguous function call. This is your cue. The most common case is calling a method on a type that has multiple same-named methods from different traits. It's also necessary when a generic function's return type cannot be inferred from the context, like with collect().
WHEN NOT TO USE IT: Avoid it when it's not necessary. Rust's type inference is powerful, so let it do its job. Over-specifying types and traits makes code verbose and harder to refactor. If instance.method() compiles, it is strongly preferred over the more explicit <MyType as MyTrait>::method(&instance).
ONE CANONICAL EXAMPLE: Imagine a struct Bar implements two traits, Pretty and Ugly, and both traits define a print() method. A call like bar.print() is ambiguous and will fail to compile. To fix this, you must specify which trait's method to use: <Bar as Pretty>::print(&bar) calls the Pretty version, while <Bar as Ugly>::print(&bar) would call the other.
Read the original → doc.rust-lang.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.