0

I have the following (simplified) code, which came up while generalizing the mechanism from my previous question to a callback argument which has a lifetime.

struct ThingWithLifetime<'a> {
    borrowed_thing: &'a i32,
}

fn process<Arg, Func>(f: Func)
where
    Func: FnMut(Arg) + 'static,  // I think here I'd need something like `for<'a> FnMut(Arg<'a>)
    Arg: Argument<Func = Box<dyn FnMut(Arg)>>,
{
    <Arg as Argument>::process_boxed(Box::new(f))
}

trait Argument {
    type Func;
    fn process_boxed(func: Self::Func);
}

impl Argument for ThingWithLifetime<'_> {
    type Func = Box<dyn for<'b> FnMut(ThingWithLifetime<'b>)>;
    fn process_boxed(func: Self::Func) {}
}

fn main() {
    let cb = |_msg: ThingWithLifetime<'_>| {};
    process(cb);
}

It gives an error

25 |     process(|_msg: ThingWithLifetime<'_>| {});
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other

   = note: expected struct `Box<(dyn for<'b> FnMut(ThingWithLifetime<'b>) + 'static)>`
              found struct `Box<(dyn FnMut(ThingWithLifetime<'_>) + 'static)>

How can I adjust the process() function to make this work with the given Argument trait and impl? I think I need to express that Func should not be tied to any specific lifetime of its argument.

I tried various things, like adding for<'a> in various places to the trait bounds of process(), but none of them worked. I also tried changing main() to process(|_msg: ThingWithLifetime<'_>| {}) because type inference around closures can be tricky, but that did not help either.

nnnmmm
  • 7,964
  • 4
  • 22
  • 41
  • See https://stackoverflow.com/questions/70591386/calling-a-generic-async-function-with-a-mutably-borrowed-argument/70592053#70592053 for a similar example. – Chayim Friedman Sep 22 '22 at 12:18
  • Thanks, but I'm not sure yet how to transfer that approach to my problem. – nnnmmm Sep 22 '22 at 12:50

0 Answers0