In the vec! macro implementation there is this rule:
($($x:expr),+ $(,)?) => (
$crate::__rust_force_expr!(<[_]>::into_vec(box [$($x),+]))
);
What exactly is that <[_]> in it?
In the vec! macro implementation there is this rule:
($($x:expr),+ $(,)?) => (
$crate::__rust_force_expr!(<[_]>::into_vec(box [$($x),+]))
);
What exactly is that <[_]> in it?
Breaking down the specific parts of the syntax:
<T>::f is the syntax to explicitly call f associated with a type T. Usually just T::f is enough, but pedantically, :: requires a path, which is why it is used here since [_] is not. The <...> allows any type to be used as a path. See Why do I need angle brackets in <$a> when implementing macro based on type?[T] is the type denoting a slice of type T._ used as a type is a placeholder or "wildcard". It is not a type itself, but serves to indicate that the type should be inferred. See What does it mean to instantiate a Rust generic with an underscore?Let's go step by step to see how <[_]>::into_vec(box [$($x),+]) produces a Vec:
[$($x),+] expands to an array of input elements: [1, 2, 3]box ... puts that into a Box. box expressions are nightly-only syntax sugar for Box::new: box 5 is syntax sugar for Box::new(5) (actually it's the other way around: internally Box::new uses box, which is implemented in the compiler)<[_]>::into_vec(...) calls the to_vec method on a slice containing elements that have an inferred type ([_]). Wrapping the [_] in angled brackets is needed for syntactic reasons to call an method on a slice type. And into_vec is a function that takes a boxed slice and produces a Vec:
pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
// ...
}
This could be done in many simpler ways, but this code was fine-tuned to improve the performance of vec!. For instance, since the size of the Vec can be known in an advance, into_vec doesn't cause the Vec to be reallocated during its construction.