I want to be able to create a Vec of unit structs that implement a sized trait (preferably without using a Box<T>
).
Here is what I want to be able to do, but It fails and says that ProgrammingLanguage
cannot be made into a trait object:
struct Python;
struct Rust;
trait ProgrammingLanguage: Sized {
fn say_hello_world() -> ();
}
impl ProgrammingLanguage for Python {...}
impl ProgrammingLanguage for Rust {...}
// Fails because ProgrammingLanguage cannot be made into a trait object
let foo = Vec::<ProgrammingLanguage>::from([Python, Rust]);
The Sized
trait would not help you here. All it can guarantee is that any particular implementation of the trait is sized, i.e. that you can not implement it on [u8]
or dyn OtherTrait
; but the dyn ProgrammingLanguage
itself is always unsized, by definition. The reason for this is quite simple: size of the trait object is defined as the size of an original type, and there's no way to statically guarantee that every type implementing the trait would have the same size.
However, there's no real reason to avoid Box
. As was mentioned in the comments, Box<UnitStruct>
is essentially just a never-dereferenced dangling pointer, without any allocation at all:
struct Rust;
fn main() {
println!("{:p}", Box::new(Rust)); // prints `0x1`
}
When you convert it to the trait object, pointer itself doesn't change - compiler just adds the vtable pointer, which is necessary for any operations with trait objects anyway.