fn wrap_fn<F>(f: F) -> F where F: for<'a> Fn(&'a str) -> &'a str { // 2
The data type (closure) must work for any lifetime 'a the caller supplies.
let f = wrap_fn(|_| i);
f(&'static "")
i has a limited lifetime and the compiler isn't allowed to go beyond it.
A2 (works)
This time the lifetime for path is 'static. The call with the limited lifetime i gets used. 'static is a subtype of all lifetimes. Variance allows the compiler to return it as the supertype.
A1
Is a longstanding bug in the compiler. The lifetime of the returned closure gets merged with the return value of it getting called.
Split over two lines to make work.
It seems like if we don't specify lifetimes in wrap_fn the compiler assumes it's 'static so that the argument and the return Fn matches. In that case, the closure captures the value forever, causes the lifetime error.
fn wrap_fn<F>(f: F) -> impl Fn(&str) -> &str where F: Fn(&str) -> &str { // 1
//fn wrap_fn<F>(f: F) -> F where F: Fn(&str) -> &str { // 2
//fn wrap_fn<'b, F>(f: F) -> F where F: Fn(&'b str) -> &'b str { // 3
f
}
/// 1: Er, borrowed value does not live long enough
/// 2: Ok
/// 3: Ok
//fn foo(i: &str) -> &str {
// let path: &str = "foo";
// wrap_fn(|_| path)(i)
//}
/// 1: Ok
/// 2: Ok
/// 3: Ok
//fn foo(i: &str) -> &str {
// let path: &str = "foo";
// let x = wrap_fn(|_| path)(i);
// x
//}
/// 1: Er, lifetime of reference outlives lifetime of borrowed content
/// 2: Er, lifetime of reference outlives lifetime of borrowed content
/// 3: Ok
//fn foo(i: &str) -> &str {
// let path: &str = "foo";
// wrap_fn(|_| i)(i)
//}
/// 1: Er, lifetime of reference outlives lifetime of borrowed content
/// 2: Er, lifetime of reference outlives lifetime of borrowed content
/// 3: Ok
fn foo(i: &str) -> &str {
let path: &str = "foo";
let s;
{
let f = wrap_fn(|_| i);
s = f(path);
}
s
}