I've got a trait that would be a #[marker]
trait if that attribute were stable. In particular, its meaning doesn't depend on which impl is applicable, just that any impl is applicable. In order to avoid blanket impl conflicts, I use a "reason" parameter, denoted R
:
trait Foo {}
trait Bar {}
trait Baz<R> {}
enum BecauseFoo {}
enum BecauseBar {}
impl<T: Foo> Baz<BecauseFoo> for T {}
impl<T: Bar> Baz<BecauseBar> for T {}
This works, but the usability is pretty bad, especially when more complex impls are added. In particular, whenever multiple impls are applicable, the user will get a type inference ambiguity error and they will be required to specify a particular "reason" in order to disambiguate and make the error go away:
impl Foo for () {}
impl Bar for () {}
fn takes_baz<T: Baz<R>, R>() {}
fn main() {
takes_baz::<(), _>();
}
Here's the error:
error[E0283]: type annotations needed
--> src/main.rs:21:5
|
21 | takes_baz::<(), _>();
| ^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `R` declared on the function `takes_baz`
|
note: multiple `impl`s satisfying `(): Baz<_>` found
--> src/main.rs:11:1
|
11 | impl<T: Foo> Baz<BecauseFoo> for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12 |
13 | impl<T: Bar> Baz<BecauseBar> for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `takes_baz`
--> src/main.rs:15:17
|
15 | fn takes_baz<T: Baz<R>, R>() {}
| ^^^^^^ required by this bound in `takes_baz`
My question is: Is there any way to coax Rust into just picking one of the impls arbitrarily rather than complaining that it can't figure out which one to use?