I would like to write a function which returns structs which are implementing a common trait.
If my function specifies the return type -> impl MyTrait
, I fail to be compliant when using a match because the match must return the same type. Example:
fn get_a_struct(an_enum: MyEnum) -> impl MyTrait {
match an_enum {
MyEnum::MyEnumFoo => MyStruct1 {},
MyEnum::MyEnumBar => MyStruct2 {},
}
}
Which produces:
error[E0308]: match arms have incompatible types
--> src/main.rs:22:5
|
22 | / match an_enum {
23 | | MyEnum::MyEnumFoo => MyStruct1{},
24 | | MyEnum::MyEnumBar => MyStruct2{},
| | ------------- match arm with an incompatible type
25 | | }
| |_____^ expected struct `MyStruct1`, found struct `MyStruct2`
|
= note: expected type `MyStruct1`
found type `MyStruct2`
If I try it with a Box
, like this:
trait MyTrait {
fn my_func() {}
}
enum MyEnum {
MyEnumFoo,
MyEnumBar,
}
struct MyStruct1 {}
struct MyStruct2 {}
impl MyTrait for MyStruct1 {
fn my_func() {
println!("Hello world from MyStruct1")
}
}
impl MyTrait for MyStruct2 {
fn my_func() {
println!("Hello world from MyStruct2")
}
}
fn get_a_struct(an_enum: MyEnum) -> Box<MyTrait> {
match an_enum {
MyEnum::MyEnumFoo => Box::new(MyStruct1 {}),
MyEnum::MyEnumBar => Box::new(MyStruct2 {}),
}
}
error[E0038]: the trait `MyTrait` cannot be made into an object
--> src/main.rs:21:1
|
21 | fn get_a_struct(an_enum: MyEnum) -> Box<MyTrait> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` cannot be made into an object
|
= note: method `my_func` has no receiver
I don't know how to use a trait in this case.
How can I write a function which returns structs which are implementing the same trait?
A partial response can be found in Why can impl trait not be used to return multiple / conditional types?, but none of the answers address the object-safety issue.
Similar behaviour in OOP can specify a return type by an interface.