Hidden type captures lifetime that does not appear in bounds, but return value doesn't capture references

I have a function that takes an impl Trait and returns an impl Trait + 'static. The input value can be a reference, but that reference is not captured by the output.

struct Foo;

trait Input {}
impl Input for &Foo {}

trait Output {}
impl Output for () {}

// this compiles fine on its own
fn takes_generic(val: impl Input) -> impl Output + 'static { }

// this does not
fn takes_concrete<'a>(s: &'a Foo) -> impl Output + 'static {
    takes_generic(s)
}

However, I get the following error:

error[E0700]: hidden type for `impl Output + 'static` captures lifetime that does not appear in bounds

It works fine if Input is instead implemented for Foo and the argument is passed by value, but in my real code, I'd prefer not to clone the input for each call.

How can I convince Rust that that output is in fact not capturing a lifetime?

I've seen a few topics relating to this error, but not the same. I did see this issue but that seems to have been fixed in 1.69.

Playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=44854d3a71a61842edc80f99d9c6977b

You need smarter return-position impl Trait that realizes the generic parameter can't be captured in the opaque return type, or you need type alias impl Trait to work around it.

1 Like

Dang that's an old issue! In my case I sort of got around it by changing the signature of takes_generic to use a Cow instead. Worse ux but not terrible.

Thanks!