'Why does this closure require inlining or `dyn`? What does `dyn` do here?

I'm confused about what's going on with lifetimes below:

struct Foo{}
impl Foo {
    fn foo(&self, _s: &str) {}
}

fn main() {
    let foo = &Foo{};
    let closure = |s| foo.foo(s);

    // Part 1: error message about wrong lifetime in FnOnce
    take_closure(closure); 

    // Part 2: no error when inlined
    take_closure(|s| foo.foo(s));

    // Part 3: no error when `dyn`d and given explicit signature
    let closure: &dyn Fn(&str) -> _ = &|s| foo.foo(s);
    take_closure(closure);
}

fn take_closure(f: impl Fn(&str) -> ()) {
    let s = get_string();
    f(&s)
}

fn get_string() -> String {
    "".to_string()
}

playground

  1. Why does Part 1 error?
  2. Why does Part 2 not error?
  3. Why does Part 3 not error and what actually happens in part 3? Does Rust make a vtable? The LLVM outputs differ between 2 and 3
  4. Is there a better way? Inlining is ugly and dyn is both ugly and makes me wonder about what it actually does.


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source