Can someone explain the lifetime rule with impl Trait in this example to me?

Given this simplified case

trait Future {}
impl Future for () {}

fn may_borrow<T>(_val: &T) -> impl Future {}

struct Foo<'a> {
    bar: &'a Vec<String>,
}

// https://github.com/rust-lang/rust/issues/42940 same issue?
fn ko() -> impl Future {
    let foo = Foo { bar: &Vec::new() };
    may_borrow(&foo)
}

// why is this ok?
fn ok() -> impl Future {
    let foo: Vec<String> = Vec::new();
    may_borrow(&foo)
}

The compiler complains the ko function:

error[E0597]: borrowed value does not live long enough
  --> src/lib.rs:12:27
   |
12 |     let foo = Foo { bar: &Vec::new() };
   |                           ^^^^^^^^^^ temporary value does not live long enough
13 |     may_borrow(&foo)
14 | }
   | - temporary value only lives until here
   |
   = note: borrowed value must be valid for the static lifetime...

while the ok function is fine.

playground link: Rust Playground

I kind of get why the return type of ko function needs static liftetime bound, but I don't understand why the ok function doesn't.

The issue and RFC link explain a big part of it.
When you write -> impl Trait it automatically grabs the lifetime of all type parameters. AFAIK there is no override; Only boxing instead. (Typically you might make the type parameter 'static.)
In essence the lifetimes expand to;
fn may_borrow<'a, 'b, T:'b>(_val: &'a T) -> impl Future + 'b {}

ko and ok both are returning unbounded 'static due to nothing else added.
The difference then becomes the choice of 'b. ko using a referential structure makes this bound.

The implementation detail does not play a part, i.e. even though () is 'static the evaluation is done for generic case.