Co_42
Co_42

Reputation: 1269

Closure as function parameter "cannot infer an appropriate lifetime due to conflicting requirements"

I am trying to use a closure as function parameter:

fn foo(f: Box<Fn() -> bool>) -> bool {
    f()
}

fn main() {
    let bar = 42;
    foo(Box::new(|| bar != 42));
}

but I get this lifetime error:

src/main.rs:7:24: 7:36 error: cannot infer an appropriate lifetime due to conflicting requirements
src/main.rs:7   let n = foo(Box::new(|| bar != 42));
                                     ^~~~~~~~~~~~
src/main.rs:7:15: 7:23 note: first, the lifetime cannot outlive the     expression at 7:14...
src/main.rs:7   let n = foo(Box::new(|| bar != 42));
                            ^~~~~~~~
src/main.rs:7:15: 7:23 note: ...so that the type `[closure src/main.rs:7:24: 7:36]` will meet its required lifetime bounds
src/main.rs:7   let n = foo(Box::new(|| bar != 42));
                            ^~~~~~~~
src/main.rs:7:15: 7:37 note: but, the lifetime must be valid for the call at 7:14...
src/main.rs:7   let n = foo(Box::new(|| bar != 42));
                            ^~~~~~~~~~~~~~~~~~~~~~
src/main.rs:7:24: 7:36 note: ...so that argument is valid for the call
src/main.rs:7   let n = foo(Box::new(|| bar != 42));
                                     ^~~~~~~~~~~~
error: aborting due to previous error

I don't understand why the lifetime is not properly infered. What can I do to fix that ?

$ rustc --version
rustc 1.0.0-nightly (6c065fc8c 2015-02-17) (built 2015-02-18)

Upvotes: 0

Views: 767

Answers (1)

oli_obk
oli_obk

Reputation: 31283

if you want to use a boxed closure you need to use move || {}.

fn foo(f: Box<Fn() -> bool>)
       -> bool {
    f()
}

fn main() {
    let bar = 42;
    let blub = foo(Box::new(move || bar != 42));
}

On the other hand, you cannot use an unboxed closure directly, as it may contain any number of captured elements, and is therefor unsized. By using generics you can easily circumvent this limitation:

fn foo<T>(f: T)
          -> bool
          where T : Fn() -> bool {
    f()
}

fn main() {
    let bar = 42;
    let blub = foo(|| bar != 42);
}

Upvotes: 3

Related Questions