Lifetime bound of closures that capture a type parameter

Consider the following (playground):

fn require_static(_: impl 'static + Fn()) {}

fn generic<T>() {}

fn works<T>() {
    require_static(|| generic::<T>());
}

fn does_not_work<T>() {
    let generic_t = generic::<T>;
    require_static(move || generic_t()); //~ `T` may not live long enough
}

fn also_does_not_work<T>() {
    require_static(generic::<T>); //~ `T` may not live long enough
}

Is it justified that works compiles but neither does_not_work nor also_does_not_work do not? It seems to me that the borrow-checker is either overly optimistic in the succeeding case or overly pessimistic in the failing cases. I'm struggling to see how the latter two can be unsound whilst the former is sound.

In particular, in works the closure || generic::<T>() is determined to satisfy a 'static lifetime bound: however it (and therefore generic::<T>) might not be invoked until after T is no longer valid. I haven't been able to exploit this to demonstrate unsoundness, but it feels to me that it shouldn't be allowed?

Is this a known issue, or have I misunderstood the situation?

(This is a spin-off from rust - "The parameter type `T` must be valid for the static lifetime" Only when not in `async` block - Stack Overflow).

1 Like

There are a few somewhat related issues.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.