42

I would like to create an array of vectors:

fn main() {
    let v: [Vec<u8>; 10] = [Vec::new(); 10];
}

However, the compiler gives me this error:

error[E0277]: the trait bound `std::vec::Vec<u8>: std::marker::Copy` is not satisfied
 --> src/main.rs:2:28
  |
2 |     let v: [Vec<u8>; 10] = [Vec::new(); 10];
  |                            ^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::vec::Vec<u8>`
  |
  = note: the `Copy` trait is required because the repeated element will be copied
0

4 Answers 4

23

You could use the Default trait to initialize the array with default values:

let array: [Vec<u8>; 10] = Default::default();

See this playground for a working example.

Sign up to request clarification or add additional context in comments.

1 Comment

This only works for [Vec<T>; N] where N <= 32 because Rust only implements the Default trait for arrays of sizes from 0 to 32 (inclusive).
18

You cannot use the [expr; N] initialisation syntax for non-Copy types because of Rust’s ownership model—it executes the expression once only, and for non-Copy types it cannot just copy the bytes N times, they must be owned in one place only.

You will need to either:

  1. Write it out explicitly ten times: let v: [Vec<u8>; 10] = [vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![], vec![]], or

  2. Use something like a vector instead of the array: std::iter::repeat(vec![]).take(10).collect::<Vec<_>>().

See also:

11 Comments

Copy is about a data type being represented precisely by its bytes, so that merely copying the bytes is enough to copy the value. This won't do for Vec because the actual data is stored in a heap allocation rich must be uniquely owned. A memory copy of a Vec would violate memory safety.
I have the very same issue handling an array of 256 vectors :(
@mfirry: writing something out 256 times isn't actually that bad, you know.
Nearly a year later now. Surely there's a good way to do this by now?
There are a few related crates. arr_macro would expand arr![vec![]; 3] to [vec![], vec![], vec![]]. array-init lets array_init(Vec::new) produce an array of up to 512 elements. No good solution can exist until const generics stabilise, and that’s still some way off. The array-init approach will then finally be good.
|
2

You can only instantiate arrays in such fashion if the type implements the Copy trait. This trait is only for types that can be copied byte by byte (and since vector points to heap, it can't be implemented).

One answer to this problem is the array_init crate that provides much more general way of initializing arrays in complicated fashion.

let multi: [Vec<u8>; 10] = array_init::array_init(|_| vec![0; 24]);

Comments

1

Nowadays you can use try_into.

fn main() {
    let x: [Vec<u8>; 10] = vec![Vec::new(); 10].try_into().expect("static");
}

I don't know when this has been introduced though.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.