It’s a placeholder. In this context, it means that there isn’t enough information for the compiler to infer a type.
You can use this in your code to make the compiler infer the type for you. For example:
pub fn main() {
let letters: Vec<_> = vec!["a", "b", "c"]; // Vec<&str>
}
This is particularly handy because in many cases you can avoid using the “turbofish operator”:
fn main() {
let bar = [1, 2, 3];
let foos = bar.iter()
.map(|x| format!("{}", x))
.collect::<Vec<String>>(); // <-- the turbofish
}
vs
fn main() {
let bar = [1, 2, 3];
let foos: Vec<_> = bar // <-- specify a type and use '_' to make the compiler
// figure the element type out
.iter()
.map(|x| format!("{}", x))
.collect(); // <-- no more turbofish
}