Hi,
I hit an interesting issue with async closure, I have code like this (with rustc 1.85), cut to minimum:
pub fn required_rolex<T>(
role: impl Into<Role>,
) -> impl AsyncFn(ApiClaim, Request, Next) -> Response
where
{
let inner_fn = async move |claim: ApiClaim, req: Request, next: Next| {
if !claim.has_role(&role.into()) {
return StatusCode::FORBIDDEN.into_response();
}
StatusCode::OK.into_response()
};
inner_fn
}
which gives me this rather cryptic error:
error[E0277]: the trait bound `i32: ops::async_function::internal_implementation_detail::AsyncFnKindHelper<i8>` is not satisfied
--> crates/mbs4-app/src/auth/token.rs:53:6
|
53 | ) -> impl AsyncFn(ApiClaim, Request, Next) -> Response
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ops::async_function::internal_implementation_detail::AsyncFnKindHelper<i8>` is not implemented for `i32`
When changing to normal closure:
pub fn required_rolex<T>(role: impl Into<Role>) -> impl Fn(ApiClaim, Request, Next) -> Response
where
{
let inner_fn = move |claim: ApiClaim, req: Request, next: Next| {
if !claim.has_role(&role.into()) {
return StatusCode::FORBIDDEN.into_response();
}
StatusCode::OK.into_response()
};
inner_fn
}
I also receive error, but this time much more clear:
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
--> crates/mbs4-app/src/auth/token.rs:54:20
|
51 | pub fn required_rolex<T>(role: impl Into<Role>) -> impl Fn(ApiClaim, Request, Next) -> Response
| -------------------------------------------- the requirement to implement `Fn` derives from here
...
54 | let inner_fn = move |claim: ApiClaim, req: Request, next: Next| {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this closure implements `FnOnce`, not `Fn`
55 | if !claim.has_role(&role.into()) {
| ---- closure is `FnOnce` because it moves the variable `role` out of its environment
...
60 | inner_fn
| -------- return type was inferred to be `{closure@crates/mbs4-app/src/auth/token.rs:54:20: 54:68}` here
And yes this seems to be the cause - changing to AsyncFnOnce in first case solves the issue.
I hope I guess cause right.