惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
博客园 - 三生石上(FineUI控件)
博客园 - 司徒正美
博客园_首页
J
Java Code Geeks
V2EX - 技术
V2EX - 技术
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
TaoSecurity Blog
TaoSecurity Blog
T
Troy Hunt's Blog
Forbes - Security
Forbes - Security
Schneier on Security
Schneier on Security
Hugging Face - Blog
Hugging Face - Blog
PCI Perspectives
PCI Perspectives
O
OpenAI News
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Hacker News: Ask HN
Hacker News: Ask HN
Application and Cybersecurity Blog
Application and Cybersecurity Blog
H
Heimdal Security Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
博客园 - 聂微东
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
大猫的无限游戏
大猫的无限游戏
WordPress大学
WordPress大学
美团技术团队
V
V2EX
Cisco Talos Blog
Cisco Talos Blog
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
C
Cybersecurity and Infrastructure Security Agency CISA
有赞技术团队
有赞技术团队
腾讯CDC
Cloudbric
Cloudbric
Google DeepMind News
Google DeepMind News
博客园 - 【当耐特】
SecWiki News
SecWiki News
IT之家
IT之家
C
Cisco Blogs
雷峰网
雷峰网
aimingoo的专栏
aimingoo的专栏
B
Blog RSS Feed
S
Schneier on Security
Security Latest
Security Latest
Scott Helme
Scott Helme
H
Help Net Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Palo Alto Networks Blog
L
LINUX DO - 热门话题
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

Rust Blog

Security Advisory for Cargo (CVE-2026-5223) | Rust Blog Security Advisory for Cargo (CVE-2026-5222) | Rust Blog Project goals update — April 2026 (end of 2025H2) | Rust Blog Rust is participating in Outreachy | Rust Blog Raising the baseline for the `nvptx64-nvidia-cuda` target | Rust Blog Announcing Google Summer of Code 2026 selected projects | Rust Blog Announcing Rust 1.95.0 | Rust Blog docs.rs: building fewer targets by default | Rust Blog Changes to WebAssembly targets and handling undefined symbols | Rust Blog Announcing Rust 1.94.1 | Rust Blog Security advisory for Cargo | Rust Blog What we heard about Rust's challenges | Rust Blog Call for Testing: Build Dir Layout v2 | Rust Blog Announcing rustup 1.29.0 | Rust Blog Announcing Rust 1.94.0 | Rust Blog 2025 State of Rust Survey Results | Rust Blog Rust debugging survey 2026 | Rust Blog Update on the October 15, 2018 incident on crates.io Announcing Rust 1.29.2 Announcing Rust 1.29 Announcing Rust 1.28 What is Rust 2018? Announcing Rust 1.27.2 Announcing Rust 1.27.1 Security Advisory for rustdoc Announcing Rust 1.27 Announcing Rust 1.26.2 Announcing Rust 1.26.1 Rust turns three Announcing Rust 1.26 The Rust Team All Hands in Berlin: a Recap Increasing Rust’s Reach 2018 Announcing Rust 1.25 Rust's 2018 roadmap Announcing Rust 1.24.1 Announcing Rust 1.24 The 2018 Rust Event Lineup Announcing Rust 1.23 New Year's Rust: A Call for Community Blogposts Rust in 2017: what we achieved Announcing Rust 1.22 (and 1.22.1) Fearless Concurrency in Firefox Quantum Announcing Rust 1.21 impl Future for Rust Rust 2017 Survey Results Announcing Rust 1.20 Announcing Rust 1.19 The 2017 Rust Conference Lineup Rust's 2017 roadmap, six months in Increasing Rust’s Reach Announcing Rust 1.18 Two years of Rust The Rust Libz Blitz Launching the 2017 State of Rust Survey Announcing Rust 1.17 Announcing Rust 1.16 Rust's language ergonomics initiative Announcing Rust 1.15.1 Rust's 2017 roadmap Announcing Rust 1.15 Announcing Rust 1.14 Announcing the First Underhanded Rust Contest Announcing Rust 1.13 Announcing Rust 1.12.1 Announcing Rust 1.12 Incremental Compilation Announcing Rust 1.11 Shape of errors to come The 2016 Rust Conference Lineup Announcing Rust 1.10 State of Rust Survey 2016 Announcing Rust 1.9 One year of Rust Taking Rust everywhere with rustup Launching the 2016 State of Rust Survey Cargo: predictable dependency management Introducing MIR Announcing Rust 1.8 Announcing Rust 1.7 Announcing Rust 1.6 Announcing Rust 1.5 Announcing Rust 1.4 Announcing Rust 1.3 Rust in 2016 Announcing Rust 1.2 Rust 1.1 stable, the Community Subteam, and RustCamp Announcing Rust 1.0 Abstraction without overhead: traits in Rust Rust Once, Run Everywhere Mixing matching, mutation, and moves in Rust Fearless Concurrency with Rust Announcing Rust 1.0 Beta Announcing Rust 1.0.0.alpha.2 Rust 1.0: status report and final timeline Announcing Rust 1.0 Alpha Rust 1.0: Scheduling the trains Yehuda Katz and Steve Klabnik are joining the Rust Core Team Cargo: Rust's community crate host Stability as a Deliverable Road to Rust 1.0
Stabilizing async fn in traits in 2023 | Inside Rust Blog
Niko Matsakis and Tyler Mandry on behalf of The Rust Async · 2023-05-03 · via Rust Blog

The async working group's headline goal for 2023 is to stabilize a "minimum viable product" (MVP) version of async functions in traits. We are currently targeting Rust 1.74 for stabilization. This post lays out the features we plan to ship and the status of each one.

In November, we blogged about nightly support for async fn in trait and identified some key next steps, most importantly support for send bounds to allow spawning in generic functions. Since then we've done a significant amount of design exploration and collected a set of case studies evaluating how well the current code works in practice.

As of now, all of the functionality described in this blog post is available on the nightly compiler. Some of this work was implemented using experimental feature gates so that we could conduct case studies and prove out viability; we are in the process of authoring RFCs for those features now (full details below).

MVP Part 1: Core support for "async functions in traits"

The easiest way to explain what we are going to stabilize is to use a code example. To start, we will permit the use of async fn in trait definitions...

trait HealthCheck {
    async fn check(&mut self) -> bool;
}

...and you can then use async fn in the corresponding impl:

impl HealthCheck for MyHealthChecker {
    async fn check(&mut self) -> bool {
        do_async_op().await
    }
}

Traits with async functions can then be used as you normally would:

async fn do_health_check(hc: impl HealthCheck) {
    if !hc.check().await {
        log_health_check_failure().await;
    }
}

Status: This functionality was described in RFC 3185, merged on Dec 7, 2021, and is available in nightly. It was covered in detail in our previous blog post.

Playground

MVP Part 2: Send bounds and associated return types

There is one complication that arises when using async functions in traits that doesn't arise with sync functions. Many async runtimes -- notably including the default configurations of Tokio and async-std -- use a work stealing thread scheduler. This means that futures may move between worker threads dynamically to achieve load balancing. As a result, the future must only capture Send data.

If you author a generic async function that spawns tasks on one of those runtimes, however, you will start to get compilation errors (playground):

async fn do_health_check_par(hc: impl HealthCheck) {
    tokio::task::spawn(async move {
        if !hc.check().await {
            log_health_check_failure().await;
        }
    });
}

The problem is that the future returned by hc.check() isn't guaranteed to be Send. It might access non-Send data. The solution is to add a Send bound, but given that this is an async function, it's not obvious how to do that. How do we talk about the future returned by a call to hc.check()? Associated return types provide the answer. We can convert the above function to use an explicit type parameter HC (instead of impl HealthCheck) and then add a new bound, HC::check(): Send. This says "the value returned by HC::check must be of Send type":

async fn do_health_check_par<HC>(hc: HC)
where
    HC: HealthCheck + Send + 'static,
    HC::check(): Send, // <-- associated return type
{
    tokio::task::spawn(async move {
        if !hc.check().await {
            log_health_check_failure().await;
        }
    });
}

Of course, it's kind of unfortunate that we had to rewrite from taking an impl HealthCheck to an explicit HC type parameter in order to use this notation. RFC 2289, "associated type bounds", introduced a compact notation to address this problem. That RFC is not part of this MVP, but if it were stabilized, then one could simply write:

async fn do_health_check_par(hc: impl HealthCheck<check(): Send> + Send + 'static) {
    //                                            -------------
    tokio::task::spawn(async move {
        if !hc.check().await {
            log_health_check_failure().await;
        }
    });
}

In our previous post, we hypothesized that this problem might not occur often in practice. However, our case studies found that it comes up quite frequently, and so we decided that a solution is needed. We explored a number of solutions and concluded that associated return types (ARTs) are a flexible and reasonably ergonomic building block, which makes them a great fit for an MVP.

Status: Associated return types have an experimental implementation and we are currently drafting an RFC. There are several open bugs that will need to be fixed. We also found that in traits with many methods, ARTs become verbose, and in the future may consider more concise syntax (see below).

Playground

MVP Part 3: "impl trait in traits" (return position)

In Rust an async function is "syntactic sugar" for a function that returns an impl Future, and async functions in traits are no exception. As part of the MVP, we plan to stabilize the use of -> impl Trait notation in traits and trait impls.

Impl trait in traits has all kinds of uses, but one common one for async programming is to avoid capturing all of the function arguments by doing some amount of sync work and then returning a future for the rest. For example, this LaunchService trait declares a launch function that does not capture self (similar to the existing Tower Service trait):

trait LaunchService {
    fn launch(
        &mut self, 
        request: Request,
    ) -> impl Future<Output = u32>;
    //   -------------------------
    //   Does not capture `self` as it does
    //   not include a `+ '_`.
}

Since async fn is sugar for a regular function returning impl Future, these two syntactic forms will work interchangeably.

trait HealthCheck {
    async fn check(&mut self) -> bool;
}

impl HealthCheck for MyType {
    fn check(&mut self) -> impl Future<Output = bool> + '_ { ... }
}

Even though the need for "impl trait in traits" comes up a lot in async, they are a general feature that will be useful in many contexts having nothing to do with async (for example, returning iterators from trait methods).

Status: Return-position impl trait in traits have an experimental implementation and are described in RFC 3425, which is currently open. This feature can stand on its own, but is an important part of the picture for async fn in traits.

Playground

Evaluating the MVP

To evaluate the utility of this MVP, the working group collected five case studies covering the builder-provider pattern used in the AWS SDK; the potential use of async function in traits in tower and the actual use in embassy, the Fuchsia networking stack and an internal Microsoft tool. These studies validated that the above functionality is sufficient to use async function in traits for all kinds of things, though some situations require workarounds (hence the "MVP" title).

What the MVP will not support or won't support well

The case studies revealed two situations that the MVP doesn't support very well, but both of them have workarounds available. These workarounds are mechanical and once the MVP is available on stable it will be possible to automate them via a custom derive or other crates on crates.io.

Modeling dynamic dispatch

In the MVP, traits that use async functions are not "dyn safe", meaning that they don't support dynamic dispatch. So e.g. given the HealthCheck trait we saw earlier, one could not write Box<dyn HealthCheck>.

At first, this seems like a crucial limitation, since many of the use cases require dynamic dispatch! But it turns out that there is a workaround. One can define an "erased" trait internally to your crate that enables dynamic dispatch. The process was pioneered by crates like erased serde and is explained in detail in the builder-provider case study.

To make this workaround easier in the near term, we plan to provide a proc macro to automate it. In the future, async fn should work with dyn Trait directly.

Send bounds are verbose, especially for traits with lots of methods

The associated return type proposal works great for traits with a single method, but it can be annoying for traits that have lots of methods. One convenient solution is to use the "trait alias pattern":1

trait SendHealthCheck
where
    Self: HealthCheck + Send,
    Self::check(): Send,
{}

impl<T> SendHealthCheck for T
where
    T: HealthCheck + Send,
    T::check(): Send,
{}

Using a pattern like this means you can write T: SendHealthCheck. We plan to provide a proc macro to write these trait aliases for you, so you can write something more like this instead:

#[make_alias(Send = "SendHealthCheck")]
trait HealthCheck {
    async fn check(&mut self) -> bool;
}

In the future, something like trait transformers may provide a more concise syntax without a proc macro. But because there are use cases that require the kind of fine-grained control provided by associated return types, we opted to stabilize them first and consider more concise syntaxes after gaining experience.

Timeline and roadmap

Our goal is to stabilize the MVP for Rust 1.74, which will be released on 2023-11-16. The branch window for this feature opens on July 14 and closes on August 24. To actually stabilize in 1.74, we want to leave room for bug fixes that may arise before the release branch is cut. The key milestones for this goal are as follows:

  • MVP implementation
  • Case study evaluations complete
  • Accepted RFC for return-position impl trait (target: 2023-05-31)
  • Accepted RFC for associated return types (target: 2023-06-15)
  • Evaluation period and bug fixing (target: 2023-06-30)
  • Stabilization report authored (target: 2023-07-01)
  • Stabilization complete for 1.74.0 (target: 2023-07-21)

You can find the complete timeline in our github project.

What comes next?

So, once this MVP is done, what next? Our next immediate goals are to ship dynamic dispatch and async closures support in 2024. Together this will complete a solid foundation to tackle future async problems, such as support for async drop, easy async iterators, or portability across runtimes.

  1. If RFC 1733 were stabilized, this would be easier.