1

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?

1

2 Answers 2

2

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.

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

1 Comment

Thank you, this was the problem. I thought Rust would know the size of the array by the amount of items listed. Reminds me of my Pascal days! But of course it needs something to differentiate between array and slice.
1

Your problem is that you cannot use & (you actually can, the problem is that you didn't actually set the array length [(i16, &dyn HC); 2]).

Also you could have use Box. But since Box::new is not const, you would need to wrap it in some other lazy wrapper, std::lazy::Lazy is not stable jet but would work:

const HC_TESTS: Lazy<[(i16, Box<dyn HC>); 2]> = Lazy::new(|| [
    (1, Box::new(Test_NTP)),
    (2, Box::new(Test_Last))
]);

Playground

Meanwhile you can use once_cell Lazy, which works the same.

Another option is to wrap all of them in a enum, so you can construct them, and impl the trait for that enum so you can use it later:

enum Tests {
    NTP(Test_NTP),
    Last(Test_Last)
}

impl<'a> HC<'a> for Tests {
    fn info(&self) -> TestInfo<'static> {
        match self {
            Self::NTP(e) => e.info(),
            Self::Last(e) => e.info()
        }
    }

    fn test(&self) -> HCResult<'a> {
        match self {
            Self::NTP(e) => e.test(),
            Self::Last(e) => e.test()
        }
    }
}


const HC_TESTS: [(i16, Tests); 2] = [
    (1, Tests::NTP(Test_NTP)),
    (2, Tests::Last(Test_Last))
];

Playground

6 Comments

You can create the entire array inside Lazy.
Why do you say he can't use &? Playground
@Jmb, oh, how does that work?. Does it allocate an static object?
@Netwave yes, so long as the object can be static allocated (e.g. no Box, Vec, maps or similar).
@Jmb, well that makes sense. I never had the need so didn't knew about it. Thanks for the tip!!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.