It's still the way to go if you want to return multiple types, unless they share a common trait. Then you can box them as such a trait object. Let's say Foo, Bar and &'a str implements the trait MyTrait. You can then do something like this:
fn foobar(key: usize) -> Box<MyTrait> {
match key {
1 => Box::new(Foo::new()), //may need to add `as Box<MyTrait>` if it isn't coerced
2 => Box::new(Bar::new()),
_ => Box::new("Something Else")
}
}
This has the consequences that they will be allocated on the heap, which is a bit costly, and you will be unable to distinguish between them unless MyTrait is implemented like Any.
Edit: or just use the Any trait directly, as @leonardo said, but that will prevent you from using the values for anything unless you unwrap them.
I think I need to rethink the model - thinking too pythony.
Essentially I'm parsing a file type, the header of which has two different versions (of different sizes), using #[repr(C)] structs atm. I think I'll probably rewrite it to read into a version-agnostic Header type instead.