36

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?

kmdreko
  • 42,554
  • 6
  • 57
  • 106
at54321
  • 8,726
  • 26
  • 46
  • 6
    Whew, Rust is generally pretty readable and intuitive, but `<[_]>::` looks like something straight out of an esolang. – Silvio Mayolo Dec 19 '21 at 18:45

2 Answers2

30

Breaking down the specific parts of the syntax:

kmdreko
  • 42,554
  • 6
  • 57
  • 106
  • 1
    For reference: [Qualified paths](https://doc.rust-lang.org/reference/paths.html#qualified-paths). – IInspectable Dec 21 '21 at 18:55
  • This answer is a perfect explanation for `<[()]>` in the Rust Macro book. https://danielkeep.github.io/tlborm/book/blk-counting.html#slice-length – Peter Mar 17 '22 at 04:26
15

Let's go step by step to see how <[_]>::into_vec(box [$($x),+]) produces a Vec:

  1. [$($x),+] expands to an array of input elements: [1, 2, 3]
  2. 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)
  3. <[_]>::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.

smitop
  • 4,770
  • 2
  • 20
  • 53