Making Sized trait objects for a known set of structs implementing the trait


#1

Is it possible to tell the compiler that I want a trait object that is Sized to accommodate a known set of structs implementing the Trait?

That is, if I have a public factory function for instantiating a Something and I have two different private somethings that implement the Something interface: FooSomething and BarSomething and I don’t want heap allocation (i.e. I don’t want the factory to return Box<Something>, can I make Something a trait and tell the compiler that the trait objects should be Sized to accommodate the larger of FooSomething and BarSomething?

Or do I need to make Something a struct that has an enum member that is a tagged union of FooSomething and BarSomething with manually-written dispatch that matches on the enum?


#2

An enum is the easiest solution, yeah. (Some macro magic would allow you to avoid having to write match in every place that dispatches.)


#3

Thanks. Ideally, there’d be a way to ask the compiler to generate the mechanic stuff instead of having to write it manually, using macros or using Python to generate Rust.


#4

I think it should be possible to implement Something for the enum and avoid macros:

trait Something {
    fn calculte(&self) -> i32;
}

struct FooSomething;

impl Something for FooSomething {
    fn calculte(&self) -> i32 { 92 }
}

struct BarSomething;

impl Something for BarSomething {
    fn calculte(&self) -> i32 { 62 }
}

enum AnySomething {
    Foo(FooSomething),
    Bar(BarSomething),
}

impl Something for AnySomething {
    fn calculte(&self) -> i32 {
        match *self {
            AnySomething::Foo(ref foo) => foo.calculte(),
            AnySomething::Bar(ref bar) => bar.calculte()
        }
    }
}


#5

This match was what I was hoping I could ask the compiler to generate for me instead of writing it in the source code.