Search code examples
arraysrustconstantstraitstrait-objects

Construct an array of objects in Rust


This is my very first Rust program that actually has a purpose and I'm still lost with the syntax. So I have trait objects like these:

trait HC<'a> {
    fn info(&self) -> TestInfo<'static>;
    fn test(&self) -> HCResult<'a>;
}

#[allow(non_camel_case_types)]
struct Test_NTP;
impl<'a> HC<'a> for Test_NTP {
    fn info(&self) -> TestInfo<'static> {
        TestInfo { ... }
    }

    fn test(&self) -> HCResult<'a> {
        ...
    }
}

#[allow(non_camel_case_types)]
struct Test_Last;
impl<'a> HC<'a> for Test_Last {
    fn info(&self) -> TestInfo<'static> {
        TestInfo { ... }
    }

    fn test(&self) -> HCResult<'a> {
        ...
    }
}

I want to construct an array of these objects those define the HC trait, tupled with an ID, so I can iterate through them and call their test() functions.

const HC_TESTS: [(i16, &dyn HC)] = [
    (1, &Test_NTP),
    (2, &Test_Last)
];

I tried several variations, but I always get a "doesn't have a size known at compile-time" error. I thought putting the objects in Boxes would solve the problem, but I get the same error:

error[E0277]: the size for values of type `[(i16, Box<&'static (dyn HC<'static> + 'static)>)]` cannot be known at compilation time
   --> src/hc.rs:125:17
    |
125 | const HC_TESTS: [(i16, Box<&dyn HC>)] = [
    |                 ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[(i16, Box<&'static (dyn HC<'static> + 'static)>)]`

The structs don't have any fields, the only reason I use them is to bound the info() and test() functions together, and I don't even use &self, they're only needed to dispatch virtual methods. What am I doing wrong?


Solution

  • Your syntax is off just slightly. The error

    the trait `Sized` is not implemented for `[(i16, Box<&'static (dyn HC<'static> + 'static)>)]

    refers to the most outer [...], which is a slice.

    In

    const HC_TESTS: [(i16, Box<&dyn HC>)] =

    you explicitly set the type of HC_TESTS to be a slice, not an array. A slice is always unsized, so the compiler complains. What you want is simply

    const HC_TESTS: [(i16, Box<&dyn HC>); 2] =

    which sets the type of HC_TESTS to be an array of exactly two elements.

    Notice that the other answers and comments here ("works for me") use this syntax as well.