Closure parameter lifetime

How to express following code in current stable Rust?

struct Foo<'a>(&'a i32);

impl<'a> Foo<'a> {
    fn id(self, _: i32) -> Foo<'a> {
        self
    }
}

fn main() {
    let c = 1; // A random capture variable to deny simple function
    let f = |a: Foo| a.id(c);   // FAIL; lifetime may not live long enough
    let f = |a: Foo<'_>| a.id(c);   // FAIL; same to above
    let f = |a| a.id(c);   // FAIL;  type annotations needed
    let f = for<'a> |a: Foo<'a>| -> Foo<'a> { a.id(c) };  // OK; But need unstable feature

    // ...
    let x = Foo(&42);
    assert_eq!(*f(x).0, 42);
}
#[macro_use]
extern crate higher_order_closure;

let g = higher_order_closure! {
    |a: Foo<'_>| -> Foo<'_> { a.id(c) }
};
let x = Foo(&42);
assert_eq!(*g(x).0, 42);

Update: the macro expansion is

    let g = ({
        fn __funnel__<__Closure>(f: __Closure) -> __Closure
        where
            __Closure: ::higher_order_closure::__::FnOnce(Foo<'_>) -> Foo<'_>,
        {
            f
        }
        __funnel__::<_>
    })(|a| { a.id(c) });

So you can do it yourself

let x = Foo(&42);
let f = adaptor(|a| a.id(c));
assert_eq!(*f(x).0, 42);

fn adaptor<F: FnOnce(Foo) -> Foo>(f: F) -> F {
    f
}
2 Likes

A simple annotation of

let f: &dyn Fn(Foo<'_>) -> Foo<'_> = &|a| a.id(c);

works as well.

4 Likes

Cool, it also works with Box

let h: Box<dyn Fn(Foo) -> Foo> = Box::new(|a| a.id(c));

The generic adaptor:

let h = adaptor::<Foo, _>(|a| a.id(c));

fn adaptor<T, F: FnOnce(T) -> T>(f: F) -> F {
    f
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.