I know there is no such thing as mutually exclusive traits, but I am following the suggestion of Lukas Kalbertodt and using associated types to help me. Please bear with me since my MWE requires a bit of boilerplate.
Assume I have Message
and Handler
traits, e.g. like in a (very) simplified version of actix. Handlers can handle messages and react accordingly. However, unlike in actix, Messages can also be assigned a priority via an associated constant like so:
use std::fmt::Debug;
trait MessageMarker {}
struct Urgent;
struct Normal;
impl MessageMarker for Urgent {}
impl MessageMarker for Normal {}
trait Message : Debug {
type Prio : MessageMarker;
}
#[derive(Debug)]
struct SayHello;
#[derive(Debug)]
struct ActivateLifeSupport;
impl Message for SayHello {
type Prio = Normal;
}
impl Message for ActivateLifeSupport {
type Prio = Urgent;
}
trait Handler<M> where M : Message {
fn handle(&self, msg : M);
}
struct MedicalDevice;
Now if I want to make my MedicalDevice
a handler for any Message, I can do that
impl<M> Handler<M> for MedicalDevice
where M : Message {
fn handle(&self, msg : M) {
println!("Received {:?}",msg);
}
}
This works completely fine. The problem comes when I want to make the device react differently to messages according to their priority:
impl<M> Handler<M> for MedicalDevice
where M : Message<Prio=Normal> {
fn handle(&self, msg : M) {
println!("Reacting slowly to {:?}",msg);
}
}
impl<M> Handler<M> for MedicalDevice
where M : Message<Prio=Urgent> {
fn handle(&self, msg : M) {
println!("Reacting urgently to {:?}",msg);
}
}
Now this produces a compiler error like so
error[E0119]: conflicting implementations of trait `Handler<_>` for type `MedicalDevice`
--> src/main.rs:53:1
|
46 | / impl<M> Handler<M> for MedicalDevice
47 | | where M : Message<Prio=Normal> {
48 | | fn handle(&self, msg : M) {
49 | | println!("Received {:?}",msg);
50 | | }
51 | | }
| |_- first implementation here
52 |
53 | / impl<M> Handler<M> for MedicalDevice
54 | | where M : Message<Prio=Urgent> {
55 | | fn handle(&self, msg : M) {
56 | | println!("Urgently {:?}",msg);
57 | | }
58 | | }
| |_^ conflicting implementation for `MedicalDevice`
To my understanding no type M
could implement both Message<Prio=Normal>
and Message<Prio=Urgent>
, so why is the compiler upset? What am I missing here?
Here is a link to the MWE in the Playground.
Thanks for your help.