Jef*_*ger 5 static rust async-await lifetime-scoping
具有一个静态引用的异步函数编译:
pub async fn test_0(_a: &'static str) {
}
Run Code Online (Sandbox Code Playgroud)
具有非静态和静态引用的异步函数编译:
pub async fn test_1<'a>(_a: &'a str, _b: &'static str) {
}
Run Code Online (Sandbox Code Playgroud)
具有三个非静态引用的异步函数编译:
pub async fn test_2<'a, 'b, 'c>(_a: &'a str, _b: &'b str, _c: &'c str) {
}
Run Code Online (Sandbox Code Playgroud)
接受两个非静态引用和一个静态引用并返回未来编译的函数:
pub fn test_3_desugared<'a, 'b>(_a: &'a str, _b: &'b str, _c: &'static str) -> impl std::future::Future<Output=()> {
std::future::ready(())
}
Run Code Online (Sandbox Code Playgroud)
那么为什么采用两个非静态引用和一个静态引用的异步函数无法编译呢?
pub async fn test_3<'a, 'b>(_a: &'a str, _b: &'b str, _c: &'static str) {
}
Run Code Online (Sandbox Code Playgroud)
有问题的编译错误:
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> src/lib.rs:11:74
|
11 | pub async fn test_3<'a, 'b>(_a: &'a str, _b: &'b str, _c: &'static str) {
| ^
|
note: hidden type `impl Future` captures lifetime smaller than the function body
--> src/lib.rs:11:74
|
11 | pub async fn test_3<'a, 'b>(_a: &'a str, _b: &'b str, _c: &'static str) {
|
Run Code Online (Sandbox Code Playgroud)
Playground 链接供参考:https://play.rust-lang.org/? version=stable&mode=debug&edition=2021&gist=4d90427b4a592ccc3b3d119a326cc401
我当前的 Rust 版本:
$ rustc --version
rustc 1.56.1 (59eed8a2a 2021-11-01)
Run Code Online (Sandbox Code Playgroud)
我在尝试将环摘要算法参数添加到已经有两个引用参数的函数时遇到了这个问题。解决方法非常简单,因为我可以将静态引用包装在一个结构中,将其传入,然后毫无问题地使用它。我只是好奇为什么会这样。
小智 3
pub fn test_3<'a, 'b>(_a: &'a str, _b: &'b str, _c: &'static str) -> impl Future
{
async {}
}
Run Code Online (Sandbox Code Playgroud)
pub async fn test_3<'a, 'b>(_a: &'a str, _b: &'b str, _c: &'static str) {
}
Run Code Online (Sandbox Code Playgroud)
版本编译的原因impl Future是因为_a、_b和_c引用不会被 future 捕获。编译器足够聪明,可以删除引用,我们可以通过函数的 HIR 看到这一点。
pub fn test_3<'a, 'b>(_a: &'a str, _b: &'b str, _c: &'static str)
-> /*impl Trait*/ { #[lang = "from_generator"](|mut _task_context| { }) }
Run Code Online (Sandbox Code Playgroud)
您可以将其与异步版本的 HIR 进行比较。在这种情况下,引用全部被捕获。
pub async fn test_3<'a, 'b>(a: &'a str, b: &'b str, c: &'static str)
-> /*impl Trait*/ where
'a:'b #[lang = "from_generator"](move |mut _task_context|
{
let a = a;
let b = b;
let c = c;
{ let _t = { () }; _t }
})
Run Code Online (Sandbox Code Playgroud)
在异步版本中,函数的所有输入生命周期都将在异步函数返回的将来捕获,如下所示impl Future + 'a + 'b + 'static。最后,所有这些生命周期都被编译器统一为一个生命周期“0”。这种统一是由成员约束算法通过“最少选择”到一组生命周期来完成的。
对于我们的具体情况,我们得到 '0 min(['a, 'b, 'static])。问题是这个集合中没有明显的最小值,因为编译器不知道 'a 和 'b 之间的关系。
如果将此信息提供给编译器,异步版本将编译
pub async fn test_3<'a, 'b>(a: &'a str, b: &'b str, c: &'static str)
where 'a:'b
{
()
}
Run Code Online (Sandbox Code Playgroud)
另一种解决方案是在没有明显最少选择的情况下选择“静态”。PR#89056对此进行了讨论
| 归档时间: |
|
| 查看次数: |
500 次 |
| 最近记录: |