This is actually an offshoot of this SO question.
Consider the following code:
trait Trait<'b> {
fn func(&'b self) {}
}
struct Struct {}
impl<'s> Trait<'s> for Struct {}
fn test<'s, T:'s>(t: T)
where
T: Trait<'s>,
{
t.func();
}
It fails, as the compiler sees that t
lives for less than the 's
and 's
is set by the caller (i.e longer than the stack-frame of the func
) and traits are invariant over type parameters. However, if I introduce HRTB (Higher Rank Trait Bounds) here, the code compiles:
fn test<T>(t: T)
where
T: for<'s> Trait<'s>,
{
t.func();
}
Now, the trait Trait<'s>
is implemented for all possible lifetimes 's
represents and accordingly the right one gets picked by the compiler.
But then why the following code fails ?
struct Temp<'a> {
x: &'a i32,
}
fn test<T>(t: T)
where
for<'s> T: 's,
{
}
fn main() {
let d = 1i32;
test(Temp { x: &d });
}
It gives the error:
error[E0597]: `d` does not live long enough
--> src/main.rs:13:20
|
13 | test(Temp { x: &d });
| ---------------^^---
| | |
| | borrowed value does not live long enough
| argument requires that `d` is borrowed for `'static`
14 | }
| - `d` dropped here while still borrowed
What is the difference here? Conceptually, I found the earlier example same as this one. Why it is expected that the concrete type T
should only be/contain reference(s) with 'static
lifetime(s) ?
for
now denotes that the lifetime of T must satisfy all possible lifetimes -- effectively meaning it must be static, and therefore d must have static lifetime too. It shouldn't be necessary to use hrtb here though, right? – Knitted