Before 1.47.0, there is the Rust array size limit size of 32. This is evident when we get the E0277 error that has the following message.
1 | arrays only have std trait implementations for lengths 0..=32 |
When Do We Get The Error?
Personally, I have never encountered this error until I read the 1.47.0 release notes.
Rust does not currently have a way to be generic over integer values. This has long caused problems with arrays, because arrays have an integer as part of their type;
[T; N]
is the type of an array of typeT
ofN
length. Because there is no way to be generic overN
, you have to manually implement traits for arrays for everyN
you want to support. For the standard library, it was decided to support up toN
of 32.
Apparently, this error happens when we treat arrays as generic values. Consider the following examples using Rust 1.46.0.
Example 1, Using format!
When we compile these codes, we will get an error on line 9.
1 2 3 4 5 6 7 8 9 10 | use std::fmt::Debug; #[derive(Copy, Clone, Debug)] struct MyType { age:i32 } fn main() { let strmyType:[MyType; 34] = [MyType{ age: 3}; 34]; let t = format!("{:?}", strmyType); } |
1 2 3 4 5 6 7 8 9 | error[E0277]: arrays only have std trait implementations for lengths 0..=32 --> src\main.rs:9:29 | 9 | let t = format!("{:?}", strmyType); | ^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[MyType; 34]` | = note: required because of the requirements on the impl of `std::fmt::Debug` for `[MyType; 34]` = note: required by `std::fmt::Debug::fmt` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) |
Example 2, Using print!
Now, consider the following codes that use the print! macro on line 9.
1 2 3 4 5 6 7 8 9 10 | use std::fmt::Debug; #[derive(Copy, Clone, Debug)] struct MyType { age:i32 } fn main() { let strmyType:[MyType; 34] = [MyType{ age: 3}; 34]; print!("{:?}", strmyType); } |
We will get the following error.
1 2 3 4 5 6 7 8 9 | error[E0277]: arrays only have std trait implementations for lengths 0..=32 --> src\main.rs:9:20 | 9 | print!("{:?}", strmyType); | ^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[MyType; 34]` | = note: required because of the requirements on the impl of `std::fmt::Debug` for `[MyType; 34]` = note: required by `std::fmt::Debug::fmt` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) |
Example 3, Trying To Make Things Generic
This is for demonstration only! Another way to look at the Rust array size limit size issue is through the following codes. We can definitely do the following.
1 2 3 4 5 | fn take_generic(myarray: [MyType; 34]) { for i in myarray.iter() { println!("{}", i.age); } } |
However, the following codes will not compile where we try to make the array size generic using the i32 type instead of a constant value.
1 2 3 4 5 | fn take_generic(myarray: [MyType; i32]) { for i in myarray.iter() { println!("{}", i.age); } } |
We will get the following error.
1 2 3 4 5 | error[E0423]: expected value, found builtin type `i32` --> src\main.rs:13:35 | 13 | fn take_generic(myarray: [MyType; i32]) { | ^^^ not a value |
Trying Out With Rust 1.47.0
Before moving on, make sure you have updated your Rust to 1.47.0.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | C:\Users\karldev>rustc --version rustc 1.46.0 (04488afe3 2020-08-24) C:\Users\karldev>rustup update info: syncing channel updates for 'stable-x86_64-pc-windows-msvc' info: latest update on 2020-10-08, rust version 1.47.0 (18bf6b4f0 2020-10-07) info: downloading component 'rls' info: downloading component 'rust-analysis' info: downloading component 'rust-src' info: downloading component 'cargo' info: downloading component 'clippy' info: downloading component 'rust-docs' info: downloading component 'rust-std' info: removing previous version of component 'rustc' info: removing previous version of component 'rustfmt' info: installing component 'rls' info: Defaulting to 500.0 MiB unpack ram info: installing component 'rust-analysis' info: installing component 'rust-src' info: installing component 'cargo' info: installing component 'clippy' info: installing component 'rust-docs' 12.9 MiB / 12.9 MiB (100 %) 3.3 MiB/s in 3s ETA: 0s info: installing component 'rust-std' 17.8 MiB / 17.8 MiB (100 %) 10.7 MiB/s in 1s ETA: 0s info: installing component 'rustc' 42.6 MiB / 42.6 MiB (100 %) 11.7 MiB/s in 3s ETA: 0s info: installing component 'rustfmt' info: checking for self-updates stable-x86_64-pc-windows-msvc updated - rustc 1.47.0 (18bf6b4f0 2020-10-07) (from rustc 1.46.0 (04488afe3 2020-08-24)) info: cleaning up downloads & tmp directories C:\Users\karldev> |
Then, you may need to restart your IDE. This time, when we run the following codes, everything will work.
1 2 3 4 5 6 7 8 9 10 | use std::fmt::Debug; #[derive(Copy, Clone, Debug)] struct MyType { age:i32 } fn main() { let strmyType:[MyType; 34] = [MyType{ age: 3}; 34]; print!("{:?}", strmyType); } |
The output generated is as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | warning: variable `strmyType` should have a snake case name --> src\main.rs:8:9 | 8 | let strmyType:[MyType; 34] = [MyType{ age: 3}; 34]; | ^^^^^^^^^ help: convert the identifier to snake case: `strmy_type` | = note: `#[warn(non_snake_case)]` on by default warning: 1 warning emitted Finished dev [unoptimized + debuginfo] target(s) in 0.79s Running `target\debug\traits-on-larger-arrays.exe` [MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }, MyType { age: 3 }] Process finished with exit code 0 |
Note that Rust 1.47.0 does not address all issues related to the Rust Array Size Limit of 32.
We have been working on a feature called “const generics” that would allow you to be generic over
N
. Fully explaining this feature is out of the scope of this post, because we are not stabilizing const generics just yet. However, the core of this feature has been implemented in the compiler, and it has been decided that the feature is far enough along that we are okay with the standard library using it to implement traits on arrays of any length.
This post is part of the Rust Programming Language For Beginners Tutorial.