Description
#[auto_impl(&)]
trait Foo {
fn foo<T>();
fn bar<U>(&self);
}
Is expanded into:
impl<'a, V: 'a + Foo> Foo for &'a V {
fn foo<T>() {
V::foo() // <-- cannot infer type for `T`
}
fn bar<U>(&self) {
(**self).bar() // <-- cannot infer type for `U`
}
}
And results in two compiler errors. So we need to change the method body into an explicit call all of the time. In this case:
V::foo::<T>()
, andV::bar::<T>(*self)
I can mentor anyone interested in tackling this issue :)
Just ping me (via email, this issue, or in any other way)
Instructions: code generation of methods is done in gen_method_item
in gen.rs
. The important part for this issue are the last two arms of the last match statement in the function (SelfType::Value
and SelfType::Ref | SelfType::Mut
). These generate incorrect code. You can see the generated code in the quote! {}
macro.
The most difficult part is probably to generate the list of generic parameters to call the other method. In the example above it's simply <T>
, but it could be more complicated. In gen_method_item()
, we have the variable sig
which is a syn::MethodSig
. We are interested in sig.decl.generics
which stores the generics of the method we are generating. Sadly, we can't just use that: e.g. fn foo<T: Clone, U>()
would have <T: Clone, U>
as generics and we can't call foo::<T: Clone, U>()
, but need to call foo::<T, U>()
. So we might have to remove all bounds. But with some luck, we can use syn::Generics::split_for_impl
. The second element of the returned tuple should be what we want. But we need to test that!
Finally, one or more compile-pass tests should be added which test this exact code.
If anything is unclear, just go ahead and ask!