I have a situation where several of my structs should implement multiple traits, but all of them implement at least one trait in common. When I get hold of a mixed bag of these structs, I want to treat them all as being of the common trait: pass them as method parameters typed to that trait, store them in collections typed for that trait, etc.
I haven't been able to figure out how to do it. Here is some code where I try to do the way it was suggested here, but it fails to compile:
trait ThingWithKeys {
fn use_keys (&self) -> String;
}
//////
trait CorrectionsOfficer {
fn hitch_up_pants (&self) -> String;
}
trait CorrectionsOfficerWithKeys: ThingWithKeys + CorrectionsOfficer {}
struct CorrectionsOfficerReal {}
impl ThingWithKeys for CorrectionsOfficerReal {
fn use_keys (&self) -> String {
String::from ("Clank, clank")
}
}
impl CorrectionsOfficer for CorrectionsOfficerReal {
fn hitch_up_pants (&self) -> String {
String::from ("Grunt")
}
}
impl <T: ThingWithKeys + CorrectionsOfficer> CorrectionsOfficerWithKeys for T {}
//////
trait Piano {
fn close_lid (&self) -> String;
}
trait PianoWithKeys: Piano + ThingWithKeys {}
struct PianoReal {}
impl ThingWithKeys for PianoReal {
fn use_keys (&self) -> String {
String::from ("Tinkle, tinkle")
}
}
impl Piano for PianoReal {
fn close_lid (&self) -> String {
String::from ("Bang!")
}
}
impl <T: ThingWithKeys + Piano> PianoWithKeys for T {}
//////
trait Florida {
fn hurricane (&self) -> String;
}
trait FloridaWithKeys: ThingWithKeys + Florida {}
struct FloridaReal {}
impl ThingWithKeys for FloridaReal {
fn use_keys (&self) -> String {
String::from ("Another margarita, please")
}
}
impl Florida for FloridaReal {
fn hurricane (&self) -> String {
String::from ("Ho-hum...")
}
}
impl <T: ThingWithKeys + Florida> FloridaWithKeys for T {}
//////
fn main() {
let corrections_officer_ref: &CorrectionsOfficerWithKeys = &CorrectionsOfficerReal {};
let piano_ref: &PianoWithKeys = &PianoReal {};
let florida_ref: &FloridaWithKeys = &FloridaReal {};
use_keys (corrections_officer_ref);
use_keys (piano_ref);
use_keys (florida_ref);
}
fn use_keys (thing_with_keys: &ThingWithKeys) {
println! ("{}", thing_with_keys.use_keys ());
}
Here are the compilation errors:
Compiling playground v0.0.1 (file:///playground)
error[E0308]: mismatched types
--> src/main.rs:80:19
|
80 | use_keys (corrections_officer_ref);
| ^^^^^^^^^^^^^^^^^^^^^^^ expected trait `ThingWithKeys`, found trait `CorrectionsOfficerWithKeys`
|
= note: expected type `&ThingWithKeys`
found type `&CorrectionsOfficerWithKeys`
error[E0308]: mismatched types
--> src/main.rs:81:19
|
81 | use_keys (piano_ref);
| ^^^^^^^^^ expected trait `ThingWithKeys`, found trait `PianoWithKeys`
|
= note: expected type `&ThingWithKeys`
found type `&PianoWithKeys`
error[E0308]: mismatched types
--> src/main.rs:82:19
|
82 | use_keys (florida_ref);
| ^^^^^^^^^^^ expected trait `ThingWithKeys`, found trait `FloridaWithKeys`
|
= note: expected type `&ThingWithKeys`
found type `&FloridaWithKeys`
error: aborting due to 3 previous errors
Essentially, it still can't find the ThingWithKeys implementation inside the XxxWithKeys implementations.