如何传递包含引用参数的异步回调?
How do I pass an async callback containing an argument that is a reference?
我有一个函数需要异步回调(请求处理程序);我目前正在尝试接受看起来像这样的东西:
async fn handle_request<'a>(request: Request, body: &'a mut (dyn AsyncRead + 'a)) -> HandlerResponse
它一直在工作,直到添加第二个参数 body
,这让我很伤心。接受参数的函数如下所示:
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>,
{
通过这个函数的一部分,我们调用了一个辅助函数:
handle_request(&mut connection, request_handler, request)
具有非常相似的签名;特别是,request_handler
的签名是相同的。它在调用 request_handler
之前进行了一些小的预处理。当我尝试编译它时,我得到:
error[E0310]: the parameter type `H` may not live long enough
|
106 | pub async fn process_requests<H, F>(
| - help: consider adding an explicit lifetime bound `H: 'static`...
...
142 | handle_request(&mut connection, request_handler, request)
| ^^^^^^^^^^^^^^
|
note: ...so that the type `H` will meet its required lifetime bounds
|
142 | handle_request(&mut connection, request_handler, request)
| ^^^^^^^^^^^^^^
为什么我需要这个/我该怎么办?确实在 where
中将 'static
添加到 H:
似乎可以消除错误,但这是正确的做法吗?实现 H
的类型不能携带引用,而 'static
会禁止这样做吗?我不一定想这样做,但是尝试将 不是 'static
的一生注释到 H
上的任何尝试都没有用;例如,'a + Fn(...) -> F + 'a
不起作用,添加新的通用 'b
生命周期也不起作用。我不想 'static
不需要它的东西,但我不知道该怎么做。
(我对消息的措辞也有点困惑——参数类型——不是一些参数或变量——没有足够长的时间。如何一种活得不够长的类型?)
我尝试了更多的东西,但我仍然无法得到任何实际编译的东西。 This playground example 显示了我 运行 遇到的另一个更令人费解的错误消息。我试过删除一些生命周期注释,并移动了 for<'a>
位(我不确定有什么区别?)。
当回调用 async
关键字标记时,作为引用传递的回调参数不适用于 HRTB 约束。
使用async/await
的签名:
async fn handle_request<'a>(request: Request, body: &'a mut (dyn AsyncRead + 'a)) -> HandlerResponse
相当于:
fn handle_request<'a>(request: Request, body: &'a mut (dyn AsyncRead + 'a)) -> Future<Output=HandlerResponse> + 'a
这意味着异步函数的输入生命周期在
异步函数返回的未来。
参见 RFC 2394 的第 "Lifetime capture in the anonymous future" 段。
声明接受参数的函数为:
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
"unlink" 从调用者绑定的生命周期并产生编译错误
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!();
}
如果可行
一种可能的解决方案是使用 Boxed 特征对象并摆脱 HTRB 约束。
我有一个函数需要异步回调(请求处理程序);我目前正在尝试接受看起来像这样的东西:
async fn handle_request<'a>(request: Request, body: &'a mut (dyn AsyncRead + 'a)) -> HandlerResponse
它一直在工作,直到添加第二个参数 body
,这让我很伤心。接受参数的函数如下所示:
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>,
{
通过这个函数的一部分,我们调用了一个辅助函数:
handle_request(&mut connection, request_handler, request)
具有非常相似的签名;特别是,request_handler
的签名是相同的。它在调用 request_handler
之前进行了一些小的预处理。当我尝试编译它时,我得到:
error[E0310]: the parameter type `H` may not live long enough
|
106 | pub async fn process_requests<H, F>(
| - help: consider adding an explicit lifetime bound `H: 'static`...
...
142 | handle_request(&mut connection, request_handler, request)
| ^^^^^^^^^^^^^^
|
note: ...so that the type `H` will meet its required lifetime bounds
|
142 | handle_request(&mut connection, request_handler, request)
| ^^^^^^^^^^^^^^
为什么我需要这个/我该怎么办?确实在 where
中将 'static
添加到 H:
似乎可以消除错误,但这是正确的做法吗?实现 H
的类型不能携带引用,而 'static
会禁止这样做吗?我不一定想这样做,但是尝试将 不是 'static
的一生注释到 H
上的任何尝试都没有用;例如,'a + Fn(...) -> F + 'a
不起作用,添加新的通用 'b
生命周期也不起作用。我不想 'static
不需要它的东西,但我不知道该怎么做。
(我对消息的措辞也有点困惑——参数类型——不是一些参数或变量——没有足够长的时间。如何一种活得不够长的类型?)
我尝试了更多的东西,但我仍然无法得到任何实际编译的东西。 This playground example 显示了我 运行 遇到的另一个更令人费解的错误消息。我试过删除一些生命周期注释,并移动了 for<'a>
位(我不确定有什么区别?)。
当回调用 async
关键字标记时,作为引用传递的回调参数不适用于 HRTB 约束。
使用async/await
的签名:
async fn handle_request<'a>(request: Request, body: &'a mut (dyn AsyncRead + 'a)) -> HandlerResponse
相当于:
fn handle_request<'a>(request: Request, body: &'a mut (dyn AsyncRead + 'a)) -> Future<Output=HandlerResponse> + 'a
这意味着异步函数的输入生命周期在 异步函数返回的未来。
参见 RFC 2394 的第 "Lifetime capture in the anonymous future" 段。
声明接受参数的函数为:
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
"unlink" 从调用者绑定的生命周期并产生编译错误
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!();
}
如果可行 一种可能的解决方案是使用 Boxed 特征对象并摆脱 HTRB 约束。