Returning a type based on condition


What’s the idiomatic way to return a different type based on a condition inside a function? Essentially a version of this that runs:

 fn foobar<A>(key: usize) -> A {
      match key {
          1 => Foo::new(),
          2 => Bar::new(),
          _ => "Something Else"

Reading other questions leads me to think it involves wrapping it in a result, custom or otherwise, but trying this leads to issues

 fn foobar<A>(key: usize) -> Result<A, String> {
      match key {
          1 => Foo::new(),
          2 => Bar::new(),
          _ => "Something Else".to_string(),

Errors being unable to infer type of let x = foobar(3) or Expected Type parameter, found struct


Something like this?

struct Foo;
struct Bar;

enum A {
    AS(&'static str)

fn foobar(key: usize) -> A {
    match key {
        1 => A::AF(Foo),
        2 => A::AB(Bar),
        _ => A::AS("Something Else")

fn main() {}

Note: Rust is a mostly statically typed language.


As far as I can tell this just shifts the problem to when I have to write an unwrap() for the enum.


There’s also the Any type. But first you have to explain what you’re trying to do, and why. And to keep in mind that Rust is statically typed.


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.


Exactly, that is the most important question.


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.