Why doesn't rust implement Debug trait for arrays conatining greater than 32 elements?

183 views
Skip to first unread message

Harikrishnan Menon

unread,
Sep 26, 2017, 1:16:55 PM9/26/17
to Rust Bangalore Community
Hi

I was trying out the following code and ran into an error.


fn main() {
let a = [12;500];
let b = [15;5];
println!("{:?}",a );
println!("{:?}",b );
}

error[E0277]: the trait bound `[{integer}; 500]: std::fmt::Debug` is not satisfied
--> src\main.rs:37:17
|
37 | println!("{:?}",a );
| ^ `[{integer}; 500]` cannot be formatted using `:?`; if it is defined in your crate, add `#[derive(Debug)]` or manually implement it
|
= help: the trait `std::fmt::Debug` is not implemented for `[{integer}; 500]`
= note: required by `std::fmt::Debug::fmt`

From https://doc.rust-lang.org/std/primitive.array.html

This limitation on the size N exists because Rust does not yet support code that is generic over the size of an array type. [Foo; 3] and [Bar; 3] are instances of same generic type [T; 3], but [Foo; 3] and [Foo; 5] are entirely different types. As a stopgap, trait implementations are statically generated up to size 32.

Could anyone please shed some light on this concept/limitation, I cant wrap my head around this.

Saifi

unread,
Sep 26, 2017, 7:28:50 PM9/26/17
to Rust Bangalore Community
Thanks Harikrishnan for bringing this up.

Rust does not yet support "integers as generic parameters.

As a result, we cannot implement a 'Debug' trait for an array of arbitrary length 'N'.

This means in an implementation, we will implement the trait for a number which we believe is adequate enough.

Since, we use a macro based implementation for efficiency, we have implemented it for length upto 32.


To understand it in some depth,

println! (note the '!') is a macro implementation.

Here is the code fragment from the file 'src/libcore/array.rs'

i've edited the file to retain the code relevant to the discussion.


/// Utility trait implemented only on arrays of fixed size

...

// macro for implementing n-element array functions and operations
macro_rules! array_impls {
($($N:expr)+) => {
$(


#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Debug> fmt::Debug for [T; $N] {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&&self[..], f)
}
}

)+
}
}

array_impls! {
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
}

// The Default impls cannot be generated using the array_impls! macro because
// they require array literals.

macro_rules! array_impl_default {
{$n:expr, $t:ident $($ts:ident)*} => {
#[stable(since = "1.4.0", feature = "array_default")]
impl<T> Default for [T; $n] where T: Default {
fn default() -> [T; $n] {
[$t::default(), $($ts::default()),*]
}
}
array_impl_default!{($n - 1), $($ts)*}
};
{$n:expr,} => {
#[stable(since = "1.4.0", feature = "array_default")]
impl<T> Default for [T; $n] {
fn default() -> [T; $n] { [] }
}
};
}

array_impl_default!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}

...

The URL to the file array.rs at github repo is at
https://github.com/rust-lang/rust/src/libcore/array.rs


The implementation above is accessed from println!.

println! (note the '!') is a macro implementation.

to work around the limitation, use the equivalent slice representation of the array,


fn main() {

let a = [12; 500];

println! ("{:?}", &a[..]);

}


Hope this helps.


warm regards
Saifi.

Harikrishnan Menon

unread,
Oct 5, 2017, 11:58:36 AM10/5/17
to Rust Bangalore Community

So if i wanted to impl Debug and Display traits for a large array is this the right way to do it?

use std::fmt;
struct myStruct {
data:[u8;300]
}

impl myStruct{
pub fn new() -> myStruct{
myStruct {
data:[2;300],
}
}
}

impl fmt::Debug for myStruct {


fn fmt(&self, f:&mut fmt::Formatter) -> fmt::Result {

fmt::Debug::fmt(&&self.data[..],f)
}
}

fn main() {
let a = myStruct::new();
println!("{:?}",a );
}

Saifi

unread,
Oct 6, 2017, 6:55:49 PM10/6/17
to rus...@googlegroups.com
The Default trait may be referenced here
https://doc.rust-lang.org/std/default/trait.Default.html

A trait for giving a type a useful Default value.

Having said that, you have wrapped an array of type T (which is a primitive type u8.) inside a struct.

Hence, you need to do two things
1. implement Default trait for struct
2. provide a default value for 'array of type T' (in this case u8).

The following code, shows a solution

use std::fmt;
struct myStruct {
data:[u8;300]
}

impl Default for myStruct{
fn default() -> myStruct {
unsafe {
std::mem::zeroed()
}
}
}

impl myStruct{
pub fn new() -> myStruct{
myStruct {
data:[2;300],
}
}
}

impl fmt::Debug for myStruct {
fn fmt(&self, f:&mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&&self.data[..],f)
}
}

fn main() {
let a = myStruct::new();
println!("{:?}",a );
}


Reply all
Reply to author
Forward
0 new messages