Odd error involving a closure that references itself

I have a trait Foo<'a>: 'a, and a closure F: FnOnce(&'a Bar) -> R where R: Foo<'a>. I'm trying to convert it to a boxed one which looks like this:

Box<dyn for<'a> FnOnce(&'a Bar) -> Box<dyn Foo<'a> + 'a>>

The problem is, it is not possible to use HRTBs for both F and R, so I have to use a workaround. Here is my try:

trait Foo<'a>: 'a {}
struct Bar;

trait Helper<'a> {
    type R: Foo<'a>;
}

impl<'a, F, R> Helper<'a> for F
where
    F: FnOnce(&'a Bar) -> R,
    R: Foo<'a>,
{
    type R = R;
}

fn poly<F>(f: F) -> Box<dyn for<'a> FnOnce(&'a Bar) -> Box<dyn Foo<'a> + 'a>>
where
    for<'a> F: 'static + Helper<'a> + FnOnce(&'a Bar) -> <F as Helper<'a>>::R,
{
    Box::new(move |b| Box::new(f(b)))
}

fn main() {
    struct FooEx<'a>(&'a Bar);
    impl<'a> Foo<'a> for FooEx<'a> {}
    let _ = poly(|x| FooEx(x));
}

I get a weird error:

error[E0644]: closure/generator type that references itself
  --> src/main.rs:26:18
   |
26 |     let _ = poly(|x| FooEx(x));
   |                  ^^^^^^^^^^^^ cyclic type of infinite size
   |
   = note: closures cannot capture themselves or take themselves as argument;
           this error may be the result of a recent compiler bug-fix,
           see issue #46062 <https://github.com/rust-lang/rust/issues/46062>
           for more information

Clearly the closure doesn't reference itself. Adding let () = x shows that x is in fact &Bar as expected. So the error message seems as a compiler bug (I've tried both stable and nightly).

The question is, how do I implement this poly function in a way that works and keeps the lifetime relationship between the argument and the return value.

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.