Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to pattern match in Rust with multiple types?

It seems as though you can't. If not, is there any planned support to add it or run-time type information (RTTI)?

struct Bus;
struct Car;
struct Person;

fn main() {
    let x = Bus;
    //or more realistically, let x = function_with_multiple_return_types();

    match x {
        Car => {
            // ...
        }
        Bus => {
            // this gets executed
        }
        Person => {
            // ...
        }
    }
}

This example is trivial. In real life, it would only be useful if x could be multiple types. e.g. let x = function_with_multiple_return_types();.

like image 802
randyrand Avatar asked Nov 10 '16 23:11

randyrand


2 Answers

No one can say with 100% accuracy that a feature will or won't ever be implemented, but I can say with 100% belief that this will never be implemented.

Why is that? Because there's zero benefit to the proposed syntax. Rust is a statically-typed language. That means that the compiler knows what the type of a variable is. There's no way that any branch besides Bus would ever be executed. There's no way that a variable can have more than one type! Why would the language change to allow you to add code that could never be used? That wouldn't be very useful.

A match statement, and pattern matching in general, is really only useful when there are multiple possible variants of something. That's why Rust has enums; to allow a fixed set of dynamic choices (a.k.a. made at runtime).

If you need an open set of dynamic decisions, that's what traits (and maybe specialization) are for. There's even a trait that allows for any concrete type.


As mentioned in the comments, you can use trait object downcasting which is provided by Any, but there's no ability to use match.

See also:

  • Can I do type introspection with trait objects and then downcast it?
like image 120
Shepmaster Avatar answered Oct 22 '22 22:10

Shepmaster


Check out std::any::Any and Andrew Johnson's link. I think you will be able to do something close to what you wanted to do using Any. fn get_type_id(&self) -> TypeId is only in the nightly builds though, so if you have the stable version of Rust you may be unable to use it yet.

This example is close to what you want, just with if let instead of match.

I wrote three examples to demonstrate how you might accomplish this, Although none are usable with match sadly... They can be found be found and run here. The following is my favorite way of doing it:

fn run_example_one() {
    let unknown_type = gen_rand_any();

    if let Some(string) = unknown_type.downcast_ref::<String>() {
       println!("It's a string!");
    } else if let Some(my_struct) = unknown_type.downcast_ref::<MyStruct>() {
        println!("my struct! name = {:?}", my_struct.my_name);
    } else if let Some(int) = unknown_type.downcast_ref::<i32>() {
       println!("something singed 32 bit int.");
   }
}
like image 30
Marek Counts Avatar answered Oct 22 '22 22:10

Marek Counts