How do you implement a trait for T where T: Foo OR Bar

In rust, you can automatically implement a trait for any type that implements some other combination of traits. Ie:

impl<T: Foo + Bar> SomeTrait for T {
    some_function(&self) {
        /*...*/
    }
}

What I'm trying to do is define a relationship where Foo and Bar are both enough to implement SomeTrait by themselves. Basically, something like this:

impl<T: Foo> SomeTrait for T {
    some_function(&self) {
        /*...*/
    }
}

impl<T: Bar> SomeTrait for T {
    some_function(&self) {
        /*...*/
    }
}

This won't compile, because you're implementing SomeTrait for T twice and the compiler can't possibly know what to do in the case where T: Foo + Bar, but it'd be really nice to be able to do this.

Is there some way to "abstract" around this problem so that I can call some_function() on a T that implements Foo OR Bar? Or am I stuck with having to pick only one implementation?


Solution 1:

If you use nightly, you can use the marker_trait_attr feature. It allows you to have overlapping impls for a trait that has the attribute #[marker]. Note that the trait should have no associated items - it must be empty.

Thus, you can define a marker trait FooOrBar (I made it in a private module so it's sealed and people cannot implement it manually):

#![feature(marker_trait_attr)]

mod private {
    #[marker]
    pub trait FooOrBar {}
    impl<T: super::Foo> FooOrBar for T {}
    impl<T: super::Bar> FooOrBar for T {}
}

And then implement the trait SomeTrait for any type that implements FooOrBar:

impl<T: private::FooOrBar> SomeTrait for T {
    fn foo(&self) { /* ... */ }
}

Playground.

For stable, unfortunately, I don't think there is a way but a redesign.