Compiler unable to match types with trait implementation
rustc 1.19.0 (0ade33941 2017-07-17)
The following piece of code:
pub struct Foo {
pub data: [u8; 64],
}
pub struct FooRef<'a> {
pub data: &'a [u8; 64],
}
impl<'a> From<&'a Foo> for FooRef<'a> {
fn from(foo: &'a Foo) -> Self {
FooRef {
data: &foo.data,
}
}
}
impl Foo {
pub fn do_something<'a, F>(&self, _foo: F) where FooRef<'a>: From<F> {
let _test_foo = FooRef::from(self);
}
pub fn do_something2<F>(&self, _foo: F) {
let _test_foo2 = FooRef::from(self);
}
}
fails with:
error[E0308]: mismatched types
--> foo/src/lib.rs:19:32
|
19 | let _test_foo = FooRef::from(self);
| ^^^^ expected type parameter, found &Foo
|
= note: expected type `F`
found type `&Foo`
error: aborting due to previous error(s)
Because of additional lifetime or template at line 19, compiler is no longer able to resolve FooRef::from(self);
Link to the repo:
https://github.com/debris/borrowchecker_test
run with cargo check -p foo
It may not be an issue, but in that case, it needs better error message. And also, please tell me how to make it work ;)
It seems you already know how to make it work: remove the where clause! This also seems to work:
pub fn do_something<'a, F>(&'a self, _foo: F) where FooRef<'a>: From<F> { let _test_foo = <FooRef as From<&Foo>>::from(self); }As for the problem itself I think it might be related to #41756:
The same mechanisms also lead to cases where:
- Adding a valid where clause can cause code to stop compiling.
- Adding a where clause can change program behavior.
Alex Burka at 2017-08-04 18:07:16
But I need this closure ;) Your example also does not work ;)
Here is my workaround:
pub fn do_something<'a, F>(&'a self, foo: F) where FooRef<'a>: From<F> { let foo_ref: FooRef = foo.into(); self.do_something_internal(foo_ref) } pub fn do_something_internal(&self, _foo: FooRef) { let _self_ref: FooRef = self.into(); // ... }Marek Kotewicz at 2017-08-04 23:25:53
My workaround does work -- note that I also added
'atoself. Your workaround is fine as well, in fact, it may even be advantageous since long generic functions lead to binary bloat (the compiler must generate separate versions of the function for each type used to call it), so doing conversions and then handing off to a non-generic is a fairly common pattern.Alex Burka at 2017-08-05 02:26:54
Yes, it works indeed, sry. And thank you very much for explanation :)
Marek Kotewicz at 2017-08-05 08:01:09
Triage: no change
Maayan Hanin at 2022-03-23 06:11:36