Specialization results in spurious mismatch type errors
An upstream crate presents me with this API:
trait Foo { }
trait Bar {
fn bar<F: Foo>(&self, f: F);
}
This is a fine API as far as it goes, but my problem is that I only care about one Foo, and I need Bar to be object safe. For my use case, this is the API I want:
struct MyFoo;
impl Foo for MyFoo { }
trait MyBar {
fn my_bar(&self, f: MyFoo);
}
But I need to bridge T: MyBar to T: Bar. I have this solution, based on specialization, which I believe is correct:
trait BarBridge<F: Foo> {
fn bridge(&self, f: F) -> F::Assoc;
}
struct Bridge<T: MyBar>(T);
impl<T: MyBar> BarBridge<MyFoo> for Bridge<T> {
fn bridge(&self, f: MyFoo) -> bool {
self.0.my_bar(f)
}
}
impl<T: MyBar, F: Foo> BarBridge<F> for Bridge<T> {
default fn bridge(&self, _: F) {
unreachable!()
}
}
impl<T: MyBar> Bar for Bridge<T> {
fn bar<F: Foo>(&self, f: F) {
self.bridge(f)
}
}
However this appears to greedily attempt to unify F with MyFoo because of the implementation of BarBridge<MyFoo> instead of recognizing the implementation of forall<F: Foo> BarBridge<F>.
cc @nikomatsakis @aturon
Hm, can you give a complete example with error? In particular, I'm not sure where this greedy unification is happening, or where you're seeing the error.
Aaron Turon at 2017-04-29 01:54:04
Here's all the code from my post in one playpen, which shows the error: https://is.gd/Kem7r0
The error is:
error[E0308]: mismatched types --> <anon>:37:21 | 37 | self.bridge(f) | ^ expected struct `MyFoo`, found type parameter | = note: expected type `MyFoo` found type `F`I've discovered that this is method dispatch specifically, if I use the canonical name it compiles:
impl<T: MyBar> Bar for Bridge<T> { fn bar<F: Foo>(&self, f: F) { <Bridge<T> as BarBridge<F>>::bridge(self, f) } }srrrse at 2017-04-29 02:01:41
Heh, yikes. I suspect at this point it probably makes sense to wait until we've got specialization up and running in Chalk, and see the results there.
Aaron Turon at 2017-04-29 02:09:37