< 返回版块

aoiryc 发表于 2024-07-06 16:15

Tags:closure,async

https://zhuanlan.zhihu.com/p/706090431

最近我写了篇博文记录了实现异步回调相关的问题,望各位审阅。

写完后我仍然好奇,除使用BoxFuture和手动实现Future外,闭包返回async block的时候真的没有办法修正返回类型上的生命周期吗?这明明只是一个历史遗留问题,但在这里影响蛮严重的。

评论区

写评论
作者 aoiryc 2024-07-07 13:21

感谢指引!

起初我只是想给想优化掉BoxFuture遇挫的朋友一些提示,但文笔不好写出来立意就偏了。的确,即使闭包的生命周期参数和函数对齐了,也只是在错误的路径上推进了一步,无法引用本体的异步回调没有多大的现实意义。

我也认识到,即使期望Lending的表达能力,也不应当在Fn*的基础上修改。「如果用的时候还要区分Lending与否,为什么不独立为一个新的Trait呢?」也同样适用在闭包上。

文章属于是在错误的路径上找问题了,只是满足一点好奇心XD

--
👇
苦瓜小仔

苦瓜小仔 2024-07-07 11:10

参考资料里竟然看到我的回答 :)谢谢你的分享

我并不认为这是一个历史遗留问题。正相反,这是一个面向未来的设计问题。

的确,在异步闭包/异步回调的泛型约束中,编译器对生命周期具有较差的支持,比如推断不够或者无法表达高阶约束。所以这主要是编译器现有的一些限制,但 rustc 开发者们目前正在完善这些,尤其是最近的焦点 RFC#3668 Async closures (即 async || {}),正如你所注意到的那样,它会挽救 || async {} 的种种尴尬局面。

实际上,在 RFC#2394 async/await 中指出,Rust 对 async block 和 async closure 都应当具有一流的支持,只是 async closure 在今年之前一直没什么推进,从而大家把闭包 + async block (或者 BoxFuture) 作为了伪异步闭包的主流做法。但实践已经证明,这种主流做法是合理的,并且社区(比如众多 Rust 服务器框架)可以忍受 BoxFuture 带来少许的效率损失,去换得稳妥的解决方案 —— 换句话说,目前闭包的限制,仅仅是最后 20% 的遗憾,但不可忽略已经存在的 80% 的成功。

闭包返回async block的时候真的没有办法修正返回类型上的生命周期吗?

无论如何,异步闭包都无法完全基于当前 Fn* 来做到。这是 lending trait 和 giving trait 天然不同的地方,lending 和 giving 无法统一(具体见 Niko 的博客吧)。

不过,顺便说一句,你可以看看 https://docs.rs/async_fn_traits,它就是你所提到的“辅助Trait”的现成解决方案。

1 共 2 条评论, 1 页