In the rust nomicon, an example of a HRTB being used is given:
struct Closure<F> {
data: (u8, u16),
func: F,
}
impl<F> Closure<F>
where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8,
{
fn call(&self) -> &u8 {
(self.func)(&self.data)
}
}
fn do_it(data: &(u8, u16)) -> &u8 { &data.0 }
fn main() {
let clo = Closure { data: (0, 1), func: do_it };
println!("{}", clo.call());
}
I roughly understand that the statement where F: for<'a> Fn(&'a (u8, u16)) -> &'a u8, is meant to relate the lifetime of the argument of the function trait to the returned reference in a generic way, a bit like universal quantification. However, what I don't understand is why the lifetime cannot simply be specified in the impl:
impl<'a, F> Closure<F>
where F: Fn(&'a (u8, u16)) -> &'a u8,
{
fn call(&self) -> &u8 {
(self.func)(&self.data)
}
}
In the similar example of a lifetime specified in a function instead of with HRTBs:
pub fn foo<'a>(x: impl Fn(&'a i32) -> &'a i32) -> i32 { let y = 42; let z = x(&y); *z }
I roughly understand that this does not work because the lifetime 'a has an implicit bound set by the function foo i.e. 'a must be longer than the function body. This thus means that this function cannot compile, as it does not account for lifetimes shorter than the lifetime of foo within the function body.
However, I don't understand why the same cannot be true of the struct impl for Closure. This stackoverflow link seems to suggest that lifetime annotations placed in impl can be thought of like generics, but for lifetimes: https://stackoverflow.com/questions/39355984/what-does-the-first-explicit-lifetime-specifier-on-an-impl-mean. Thus, since the lifetime 'a is not bounded by anything, unlike the example of the function, I would expect 'a to be parameterised correctly to the function trait, just like with the HRTB. Instead, the rust compiler gives this error:
-continued below-