






















Almost a year ago, the Async Working Group1 embarked on a collaborative effort to write a shared async vision document. As we enter 2022, we wanted to give an update on the results from that process along with the progress we are making towards realizing that vision.
To set the scene, imagine it's Rust 2024, and you've decided to build your first project in Rust. You're working on a project that uses GitHub and you'd like a tool that will walk over all the issues on your repository and do some automatic triage. You decide to use async Rust for this. You pull out the Rust book and thumb over to the Async I/O section. In there, it shows you the basic structure of an async Rust application. Like any Rust program, it begins with main, but this time with an async fn...
async fn main() {
...
}
Thumbing over to crates.io, you search for "github" and find that there is a nifty crate crabbycat for navigating github issues. You import it and sit down to work. The first thing you need to do is to to iterate over all the issues:
async fn main() {
for await? issue in crabbycat::issues("https://github.com/rust-lang/rust") {
if meets_criteria(&issue) {
println!("{issue:?}");
}
}
}
Your crate seems to be working well and you happily tweet about it. Soon enough you find yourself with some users and one of them opens a PR to extend it to to support GitLab. To do this, they introduce a trait that allows you to write code that is generic over the issue provider. This trait has one method, issues which returns an iterator (in this case, an async iterator):
trait IssueProvider {
async fn issues(&mut self, url: &str)
-> impl AsyncIterator<Item = Result<Issue, Err>>;
}
#[derive(Debug)]
struct Issue {
number: usize,
header: String,
assignee: String,
}
Now they are able to refactor the main loop into a function that is generic over the IssueProvider. They decide to use a dyn trait to avoid monomorphizing many times.
fn process_issues(provider: &mut dyn IssueProvider) {
for await? issue in provider.issues("https://github.com/rust-lang/rust") {
if meets_criteria(&issue) {
println!("{issue:?}");
}
}
}
You happily hit merge on the PR and everything works great. Later on, somebody wants to port your system to run on the Chartreuse operating system. Chartreuse is based on an actor model and uses its own custom async runtime -- but luckily for you, you don't care. All your code is seamlessly able to switch the underlying runtime implementation over to the Chartreuse async runtime.
Of course, the year is still 2022, and the vision we just painted is not reality -- at least not yet. There is a lot of work to do yet in terms of RFCing and implementing the features that will let us write the code we talked about:
IssueProvider trait requires async fns in traits.&mut dyn IssueProvider argument requires supporting dynamic dispatch in traits that have async functions
impl AsyncIterator!for await? loop, which permitted easy iteration over iterators in async code.Stream) has a different name and is not stabilized; its definition is likely to change, too, once we have strong support for async fns in traits.async fn main and changing to an alternate runtime requires portability across runtimes.As this work proceeds we can expect plenty of changes in the details along the way, and we might decide some pieces aren't worth it; if nothing else, the syntax for generators is a hotly contested topic. What won't change is the the overall vision: that writing async Rust code should be as easy as writing sync code, apart from the occasional async and await keyword.
We've organized the Async working group into a number of distinct initiatives, each of which is pursuing one part of the vision. What follows is a list of the currently active groups and some of the things they've done over the last few months since they got up and running.
Led by tmandry, currently focused on supporting async fn in traits.
Led by estebank, exploring generators and async generators.
Led by nrc, exploring what it takes to make code easily portable across runtimes, beginning with standardized traits for things like AsyncRead and AsyncWrite.
Led by eholk, focused on improving the existing capabilities via smaller changes that collectively make a big difference.
must_not_suspend lint that catches cases where values are live across an await point that should not be.Led by pnkfelix, working to support folks in the async ecosystem who are building interesting tooling to support async Rust others.
You can find the complete set of work that we have planned on our roadmap page, which also links to various deliverables we're working toward.
If you're interested in helping out, a good place to start is the How to help section of the polish initiative page. There is also a weekly polish triage meeting which you may want to attend.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。