Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

265
Vistas
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.
over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Why does Part 1 error?

Rust's type inference is not great at deciding what type a closure should have, when the closure is declared separately from where it is used. When the closure accepts references, the compiler often assumes that there is some specific lifetime that will be involved, not “any lifetime the caller cares to provide” as is actually required here.

In fact, there's an active Rust RFC to improve this by adding another way to specify lifetime parameters on closures. (The RFC also contains an example where making the opposite lifetime assumption would not work.)

what actually happens in part 3? Does Rust make a vtable?

Yes, there's a vtable involved whenever you use dyn. That's not especially relevant to the root cause here; it's just that the elided lifetime in dyn Fn(&str) got resolved the way you needed rather than the way you didn't.

Is there a better way? Inlining is ugly and dyn is both ugly and makes me wonder about what it actually does.

Placing a closure directly in the function call expression that uses it is very common Rust style, and I recommend you stick to it whenever possible, since it's also the way that works well with type inference.

As a workaround in the case where you need to use a closure more than once, you could pass the closure through a function that constrains its type:

fn string_acceptor<F: Fn(&str) -> ()>(f: F) -> F {
    f
}

...

    let foo = &Foo{};
    let closure = string_acceptor(|s| foo.foo(s));
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda