Ensuring mutual exclusivity of traits in Rust without compiler errors

Playground

Can we make it so that the compiler knows that T: LikeOne will never be LikeTwo and T: LikeTwo will never be LikeOne and not cause an error?
negative-impls and marker-trait-attr don't help.

I know about the overlap rules, but can't the error be triggered only after the trait for the type that causes the conflict is actually implemented? Because I really need this in my local crate, where traits are marker and not public, and I need this flexibility.

No, there's no support for mutually exclusive traits so far.

Conflicting implementation errors like the one in the playground are about SemVer compatibility -- what could be possible with a change that is considered non-major-breaking, and not just what actually exists today.

You can syntactically express some cases of this by combining the traits into a single trait with an associated constant or type. Associated items can't have two values, so they are necessarily mutually exclusive. However, the compiler doesn't yet make use of this information to observe lack of overlap; the following does not compile even with nightly features:

trait LikeOneOrTwo {
    const IS_TWO: bool;
}

impl<T: LikeOneOrTwo<IS_TWO = false>> From<T> for A {
    fn from(_: T) -> Self {
        unimplemented!()
    }
}

impl<T: LikeOneOrTwo<IS_TWO = true>> From<T> for A {
    fn from(_: T) -> Self {
        unimplemented!()
    }
}

But if this works for you then maybe writing a single impl works:

trait LikeOneOrTwo {
    const IS_TWO: bool;
}

impl<T: LikeOneOrTwo> From<T> for A {
    fn from(_: T) -> Self {
        if T::IS_TWO {
            unimplemented!()
        } else {
            unimplemented!()
        }
    }
}

And if you need to change the types somehow rather than just branching, an associated type rather than associated const may be able help.

4 Likes

And if it did, we would have mutually exclusive traits.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.