1 个不稳定版本

0.1.0 2021 年 12 月 20 日

#7#挂起

Apache-2.0 许可

8KB
67 行代码(不包括注释)

挂起函数

免责声明:这主要是为了证明以下提案的概念。我没有测试这个宏是否有性能成本。

此包提供了一个 proc-macro,它消除了使用 await 关键字的需要。例如

#[suspend_fn]
fn visit_rustlang() -> Result<(), reqwest::Error> {
    let response = reqwest::get("https://www.rust-lang.net.cn")?;
    let text = response.text()?;
    println!("{}", text);
    text.len(); // sync functions work just fine!
    Ok(())
}

上面的代码在功能上与以下代码等效

async fn visit_rustlang() -> Result<(), reqwest::Error> {
    let response = reqwest::get("https://www.rust-lang.net.cn").await?;
    let text = response.text().await?;
    println!("{}", text);
    text.len(); 
    Ok(())
}

挂起块

您还可以使用类似于 asyncasync move 块的 suspend!suspend_move! 宏。请注意,这些可能会提示样式警告,因此我建议将 #![allow(unused_parens)] 放在 crate 根目录中。

#![allow(unused_parens)]
suspend! { 
    let response = reqwest::get("https://www.rust-lang.net.cn")?;
    let text = response.text()?;
    println!("{}", text);
    text.len(); 
}

限制

目前,该宏在内部宏中不起作用。例如

println!("{}", async_fn());

上面的代码将引发以下错误消息

| println!("{}", async_fn()); 
|                ^^^^^^^^^^  `impl Future` cannot be formatted with the default formatter

在这种情况下,您可以在宏中自己使用 .await

动机

最近的一篇博客文章中讨论异步取消问题,有人认为异步析构函数会导致从语言设计角度不一致。这是因为编译器将为异步析构函数引入 .await 调用,使得一些 .await 调用是隐式的,而另一些是显式的。

作为解决这种冲突的一种方式,有人提出了完全删除 .await 语法。虽然我认为从人体工程学角度来看这将非常棒,但我不希望看到这样大的破坏性变化。作为替代方案,我建议添加一个新关键字,类似于 async,暂时让我们使用 Kotlin 的 suspend

然后我们就可以有

suspend fn function() {
    /* 
        implicit await with implicit calls to async destructors
    */
}
async fn function() {
    /* 
        explicit await with explicit calls to async destructors
    */
}

async {
    /* 
        explicit await with explicit calls to async destructors
    */
}

suspend {
    /* 
        implicit await with implicit calls to async destructors
    */
}

依赖项

~1.5MB
~35K SLoC