For this simple example, you don't even need to annotate U
. Instead, you can help the compiler along by clarifying that the lifetime of F
's parameter should be/will be at least as long as the reference to self
:
impl<T> Foo<T> {
fn map_ref<'a, U, F>(&'a self, f: F) -> Foo<U>
where
F: Fn(&'a T) -> U,
{
Foo(f(&self.0))
}
}
When you call foo.map_ref(f)
, what really happens under the hood is Foo::<T>::map_ref(&foo, f)
: calling a method creates a reference to the object the method is called on. So now, when we call map_ref
and give it a closure, the closure is given a parameter whose lifetime is the same length as the implicitly created &foo
.
See here on the Rust Playground. Hopefully that answers your question. :-)