What precisely does a placeholder lifetime mean in an async closure signature?
โ Rust ๐ 2026-03-21 ๐ค surdeus ๐๏ธ 1Let's say I have a struct like this that accepts a lifetime parameter:
struct S<'a>(&'a str);
What does the lifetime parameter mean in this closure?
async |_: S<'_>| { todo!() }
Given that underneath this expands to an async_call_mut method, I thought maybe it meant that the S parameter needs to have the same lifetime as the closure borrow. But I guess that doesn't make sense in the context of AsyncCallOnce, and this program compiles fine despite the closure not being 'static (playground):
struct S<'a>(&'a String);
fn check_accepts_static<F>(_: &F)
where
F: AsyncFnMut(S<'static>),
{
}
fn main() {
let f = async |_: S<'_>| todo!();
check_accepts_static(&f);
let s = String::from("taco");
f(S(&s));
}
So I now suspect that what's going on here is that the closure is generic over the lifetime associated with S. I can't find any references on thisโthe internet says that closures cannot be generic, but perhaps that means "aside from lifetimes".
Is it accurate to say that there is not one AsyncFnMut implementation, but a family of them, and they wind up looking something like this (particularly with respect to the lifetimes and their relationships to each other)?
struct SomeClosure;
struct FnMutFuture<'c, 's>(&'c mut SomeClosure, S<'s>);
impl<'s> AsyncFnMut<(S<'s>,)> for SomeClosure {
type CallRefFuture<'c> = FnMutFuture<'c, 's>;
extern "rust-call" fn async_call_mut(&mut self, args: (S<'s>,)) -> Self::CallRefFuture<'_> {
FnMutFuture(self, args.0)
}
}
I really wish there were a way to get the compiler to dump something like this for its own generated implementations, but I can't find one.
2 posts - 2 participants
๐ท๏ธ Rust_feed