Аргумент обратного вызова, переданный как ссылка, не работает с ограничениями HRTB, когда обратный вызов помечен ключевым словом async
.
Подпись с использованием async/await
:
async fn handle_request<'a>(request: Request, body: &'a mut (dyn AsyncRead + 'a)) -> HandlerResponse
Is эквивалентно:
fn handle_request<'a>(request: Request, body: &'a mut (dyn AsyncRead + 'a)) -> Future<Output=HandlerResponse> + 'a
Это означает, что время жизни входа асинхронной функции c будет зафиксировано в будущем, возвращаемом функцией асин c.
См. параграф «Захват времени жизни». в анонимном будущем "из RF C 2394 .
Объявление функции, принимающей параметр, в виде:
pub async fn process_requests<H, F>(
mut connection: Box<dyn AsyncConnection>,
request_handler: &H,
) -> Result<(), DecodeError>
where
for<'a> H: Fn(crate::Request, &'a mut (dyn AsyncRead + 'a)) -> F + 'a,
F: Future<Output = HandlerResponse>,
{
Дать ошибку компиляции, поскольку требование HRTB :
for<'a> H: Fn(crate::Request, &'a mut (dyn AsyncRead + 'a)) -> F + 'a
"отсоединить" время жизни, связанное с вызывающей стороной, и произвести ошибку компиляции expected bound lifetime parameter 'a, found concrete lifetime
, чтобы узнать больше о HRTB, см. здесь .
Чтобы это работало, вы должны написать:
pub async fn process_requests<'a, H, F>(
mut connection: Box<dyn AsyncConnection>,
request_handler: &H,
) -> Result<(), DecodeError>
where
H: Fn(crate::Request, &'a mut (dyn AsyncRead + 'a)) -> F + 'a,
F: Future<Output = HandlerResponse>,
{
Но это приведет вас к другой проблеме:
`body` does not live long enough
, потому что локальная структура тела не выживает request_handler
:
async fn handle_request<'a, H, F>(
request_handler: &H,
request: Request,
) -> io::Result<()>
where
H: Fn(Request, &'a mut (dyn AsyncRead + 'a)) -> F,
F: Future<Output = String>,
{
let mut body = Body {};
request_handler(request, &mut body);
unimplemented!();
}
Если возможно, возможно одно решение Можно использовать объекты в штучной упаковке и избавиться от ограничений HTRB.