Is there a reason unused lifetimes are captured in the return type of an async fn?

From this Clippy issue.

In this code:

async fn foo<'a>() {}

fn main() {
    let _ = foo();
}

The implicit return type of foo is impl Future<Output = ()> + 'a. Is there a reason for 'a to be captured even if it does not actually appear in the (non-generic) input parameters of the function?

I'm hesitating if this could be considered a bug, but maybe I'm missing something?

In literally this example, there's no reason that I can tell. In typical cases there is:

async fn foo<'a>(arg: &'a i32) {
}

That's because async functions don't run when they're called.

Calling async fn only takes function arguments and puts them in a Future struct (in this example something like FooFuture<'a> { arg: &'a i32 }). The code is called later when the future is polled, so the future has to be tied to lifetimes of all arguments.

This is true even when arguments with lifetimes aren't used in the function at all. Borrow checker checks based on function signatures, not function bodies.

@kornel exactly, but in this corner case the function is nullary, so the lifetime can't be used in any input type, but the desugaring ties the returned future to that lifetime anyway.

In the linked issue, the user would expect the extra_unused_lifetimes lint to be triggered, which is reasonable, but the lint does not trigger because the lifetime is used in the return type.