Aaron Turon
aturon.github.io · Personal blog · on HN since 2015
Aaron Turon, a Rust core team member, writes about Rust language design, futures, async, concurrency, and Cargo.
What HN saysHN commenters point to his posts as an excellent description of async borrowing and as an authority on lock-free and concurrent programming in Rust.
49HN people shared it
35linked it in comments
19stories submitted
1.7Kstory points
1 year agolast shared
2015people per year2026
Most-shared posts
- 1Zero-cost futures in Rust11 people · 930 points · first shared 2016 · 337 comments on HN
- 2Lock freedom without garbage collection in Rust11 people · 235 points · first shared 2015 · 90 comments on HN
- 3Designing futures for Rust7 people · 33 points · first shared 2016 · discussion on HN
- 4Borrowing in async code – Aaron Turon4 people · 3 points · first shared 2018 · discussion on HN
- 5The Rust Platform3 people · 362 points · first shared 2016 · 250 comments on HN
- 6Resurrecting impl Trait2 people · 11 points · first shared 2015 · 3 comments on HN
- 7Version selection in Cargo2 people · 9 points · first shared 2018 · discussion on HN
- 8Futures design2 people · first shared 2025
- 9Builders2 people · first shared 2015
- 10Async borrowing2 people · first shared 2019
- 11Closing out an incredible week in Rust1 people · 92 points · first shared 2018 · 7 comments on HN
- 12Sound and ergonomic specialization for Rust1 people · 5 points · first shared 2018 · discussion on HN
- 13Retooling the Rust Libs Team for 20181 people · 3 points · first shared 2018 · discussion on HN
- 14The Future of Tokio1 people · 2 points · first shared 2016 · discussion on HN
- 15Zero-cost Futures in Rust (2016)1 people · 2 points · first shared 2024 · discussion on HN
What HN people wrote when they linked it
steveklabnik · 2021-03-10
It is a little old, but for the general gist of it, http://aturon.github.io/tech/2018/04/24/async-borrowing/ is an amazing description of the problem here.
It is a PhD level research problem to know if monads and do notation would be able to work in Rust. The people who are most qualified to look into it (incidentally: a lot of the same crew was who was working on async) believe that it may literally be impossible.
rshm · 2017-01-19
Its a work in progress, but available bits were helpful.
http://aturon.github.io/
dbaupp · 2015-09-10
Not yet, but Aaron Turon, working full time on Rust, has a personal goal to make Rust have awesome support for these sort of things (lock-free data structures and other abstractions for concurrent programming). I suspect that Rust could very well become the "best" in this area.
You can see Aaron's initial work on the basics (memory management) on his blog[1], and a higher-level introduction into the power of Rust's concurrency on the main Rust blog (also written by Aaron)[2].
[1]: http://aturon.github.io/blog/2015/08/27/epoch/
[2]: http://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html
kibwen · 2025-08-22
> The fundamental problem is that rust async was developed when epoll was dominant (and almost no one in the Rust circles cared about IOCP)
No, this is a mistaken retelling of history. The Rust developers were not ignorant of IOCP, nor were they zealous about any specific async model. They went looking for a model that fit with Rust's ethos, and completion didn't fit. Aaron Turon has an illuminating post from 2016 explaining their reasoning: https://aturon.github.io/tech/2016/09/07/futures-design/
See the section "Defining futures":
There’s a very standard way to describe futures, which we found in every existing futures implementation we inspected: as a function that subscribes a callback for notification that the future is complete.
Note: In the async I/O world, this kind of interface is sometimes referred to as completion-based, because events are signaled on completion of operations; Windows’s IOCP is based on this model.
[...] Unfortunately, this approach nevertheless forces allocation at almost every point of future composition, and often imposes dynamic dispatch, despite our best efforts to avoid such overhead.
[...] TL;DR, we were unable to make the “standard” future abstraction provide zero-cost composition of futures, and we know of no “standard” implementation that does so.
[...] After much soul-searching, we arrived at a new “demand-driven” definition of futures.
I'm not sure where this meme came from where people seem to think that the Rust devs rejected…
withoutboats3 · 2023-09-08
Rust chose to drop the green thread library so that it could have no runtime, supporting valuable use cases for Rust like embedding a Rust library into a C binary, which we cared about. Go is not really usable for this (technically it's possible, but it's ridiculous for exactly this reason). So those sorts of users are getting a lot of benefit from Rust not having a green threading runtime. As are any users who are not using async for whatever reason.
However, async Rust is not using stackless coroutines for this reason - it's using stackless coroutines because they achieve a better performance profile than stackful coroutines. You can read all about it on Aaron Turon's blog from 2016, when the futures library was first released:
http://aturon.github.io/blog/2016/08/11/futures/
http://aturon.github.io/blog/2016/09/07/futures-design/
It is not the case that people using async Rust are getting the "worst of both worlds." They are getting better performance by default and far greater control over their runtime than they would be using a stackful coroutine feature like Go provides. The trade off is that it's a lot more complicated and has a bunch of additional moving parts they have to learn about and understand. There's no free lunch.
mleonhard · 2021-09-13
Large organizations are full processes for balancing power between internal groups. As Rust Foundation, Amazon, and other companies become more involved, friction will happen more frequently. The Rust Foundation will need processes for balancing power between the companies and various groups inside the companies.
PR pieces are usually full of deception. I expect that Rust Foundation will end up with a process for approving Rust-related PR from supporting organizations. They will pay someone to do that work.
So far, Rust has been run by people who behave reasonably. I'm confident that they will resolve this issue. They will resolve it with open discussion, expressing and acknowledging different opinions and needs, explaining tradeoffs, and progressing steadily to consensus.
Here's a great talk by previous Rust head Ashley Williams about Rust's decision-making process: https://www.youtube.com/watch?v=JLstJFvdl4s&t=1808s
Some articles about it:
- http://aturon.github.io/tech/2018/05/25/listening-part-1/#the-great-in…
- http://smallcultfollowing.com/babysteps/blog/2020/12/30/the-more-thing…
- https://rust-lang.github.io/rfcs/
Pauan · 2023-09-09
Threads cannot scale at all, because you're limited to the number of threads (which is usually quite small).
Async code can scale essentially infinitely, because it can multiplex thousands of Futures onto a single thread. And you can have millions of Futures multiplexed onto a dozen threads.
This makes async ideal for situations where your program needs to handle a lot of simultaneous I/O operations... such as a web server:
http://aturon.github.io/blog/2016/08/11/futures/
Async wasn't invented for the fun of it, it was invented to solve practical real world problems.
urschrei · 2023-09-09
crossbeam was created by Aaron Turon (who has – inevitably – also left the Rust project): https://aturon.github.io/blog/2015/08/27/epoch/
jayflux · 2021-12-08
> Why has Rust struggled so much with this, where Go has succeeded from the start with its language-level “goroutine” concept and runtime?
It’s not that Rust has struggled, it was never Rust’s priority to have a runtime or high level async code. It had very different goals to Go.
It’s like asking “why has C struggled to implement
Promises like JavaScript”? The languages serve different purposes.
You’re right it wasn’t their initial focal point but later on Rust wanted to offer the chance of having a go-like runtime without destabilising the low-level performance at the core level. I.E only those that use it pay for it and those that don’t use it aren’t affected.
Offering “zero cost” futures etc is very difficult to do.
See https://aturon.github.io/blog/2016/08/11/futures/ for more info, old but still relevant (including the chart)
withoutboats2 · 2021-03-10
https://aturon.github.io/blog/2016/09/07/futures-design/
The completion based futures that Alex started with were also based on epoll. The performance issues it presented had nothing to do any sort of impedence mismatch between a completion based future and epoll, because there is no impedence issue. You are confused.
gnomeria · 2020-08-14
That is indeed interesting. I've thought about mentioning http://aturon.github.io/sponsor/ but then I realized you said about not individuals but a team.
So I guess crowdfunded project idea is not bad at all. I mean there probably some rewards tier to have some tokens or souvenier
weiming · 2019-08-19
Going down the same rabbit hole earlier this week, found this to be a good explanation:
All of the data needed by a task is contained within its future. That means we can neatly sidestep problems of dynamic stack growth and stack swapping, giving us truly lightweight tasks without any runtime system implications. ... Perhaps surprisingly, the future within a task compiles down to a state machine, so that every time the task wakes up to continue polling, it continues execution from the current state—working just like hand-rolled code. [1]
[1] https://aturon.github.io/blog/2016/09/07/futures-design/
karavelov · 2018-12-09
Yes, the executor is that loop. Here is an older blog about Rust futures that is still relevant: http://aturon.github.io/2016/09/07/futures-design/
manaskarekar · 2018-08-08
This might be interesting reading. Comments on rust's approach to async from green thread.
https://aturon.github.io/blog/2016/08/11/futures/
epage · 2018-04-27
From the article
> This is especially true when it comes to the more complicated ones like moves and futures, but also true for simpler ones like borrows. What I didn’t know when I wrote about it in frustration a month ago is that it doesn’t take a little longer longer to be effective in Rust compared to other languages, it takes 10 to 20 times longer.
I think futures might be exacerbating the authors problems. There was a recent post [0] that does a good job explaining why futures are so hard and how the in-progress async/await features fix it.
[0] https://aturon.github.io/2018/04/24/async-borrowing/
tmandry · 2018-04-25
Rust is working on exactly this, targeting stabilization later this year: http://aturon.github.io/2018/04/24/async-borrowing/
lobster_johnson · 2017-07-27
The actual proposal is here: http://aturon.github.io/blog/2017/07/26/revisiting-rusts-modules/
geofft · 2017-04-01
Note that it's possible to use Rust's typesystem to build things that are deadlock-free and race-condition-free; see, for instance, https://aturon.github.io/blog/2015/08/27/epoch/ for an API for building lock-free data structures. The assistance you get from the Rust language is much better than the assistance you'd get from C or C++. (Rust has a lot of features other than memory safety!)
It's just that Rust doesn't consider it unsafe to build a design that permits deadlocks and race conditions.
tmzt · 2017-03-06
Something like this, in Rust?
https://aturon.github.io/blog/2016/08/11/futures/
x0x0 · 2017-02-27
I think yosef misinterpreted JWZ.
In large applications a bump pointer allocator plus generational gc is really fast (yes, stack allocation is fast too, but you can't always do it). A compacting gc avoids arenas, object reuse, or other awfulness. gc enables lock-free / CASed data structures; otherwise memory ownership is too complex to implement (though there's a Rust guy doing really cool stuff [1]). And gc in a threaded program is wildly easier. Unless you liked eg COM-style explicit ref-counting.
As for lisp plus large programs, the large program I worked on did end up with a bespoke (unfortunately) type-free internal language in order to orchestrate itself. Large = low millions of LOC of c++.
[1] https://aturon.github.io/blog/2015/08/27/epoch/
leshow · 2017-01-30
Most guys I follow are either rust or haskell developers.
@manishearth - rust - https://manishearth.github.io/
@bitemyapp - writer of haskell: first principles
@bartoszmilewski - haskell - https://bartoszmilewski.com/
@jdegoes - writes informative FP blog posts - http://degoes.net/
@aaron_turon - rust - https://aturon.github.io/blog/
@pcwalton - rust
@nikomatsakis - rust - http://smallcultfollowing.com/babysteps/
@paf31 - purescript creator
@nick_r_cameron - rust
@kmett - famous haskeller
@steveklabnik - rust - http://words.steveklabnik.com/
vog · 2016-08-22
My big hope in this regard is Rust, which has a very good track record if implementing good, usable, zero-cost abstractions.
If they manage to implement zero-cost futures [1][2], maybe they will also implement sime kind of zero-cost error handling abstraction (either via exceptions, or via some other useful abstraction for that purpose).
[1] https://aturon.github.io/blog/2016/08/11/futures/
[2] https://news.ycombinator.com/item?id=12268988
aturon · 2016-08-11
No, it's more related to the fact that Rust allows you to use traits in both a statically- and dynamically-dispatched way. You can read some more on the topic here: http://aturon.github.io/blog/2015/09/28/impl-trait/
gue5t · 2016-07-26
Related: epochs and lockfree data structures in crossbeam https://aturon.github.io/blog/2015/08/27/epoch/
dikaiosune · 2016-01-31
Does C++ have the ability to safely share stack data without copying? I don't think so, but I'm not an expert.
Rust has a few libraries that enable stack-scoped threads that are safe by virtue of ensuring that all threads created in the scope terminate before the data they reference is dropped (EDIT: and by preventing mutation of shared state without guarantees about atomic operations).
For example, I'm working on a project that uses crossbeam:
https://aturon.github.io/crossbeam-doc/crossbeam/
And there's a good blog post explaining some other things the library does:
https://aturon.github.io/blog/2015/08/27/epoch/
nikic · 2015-12-03
Having a GC can make the implementation of lock-free data structures significantly easier. Without GC you effectively end up implementing a sort of very specialized garbage collection scheme for the data structure.
This is a very nice article about using epoch-based memory reclamation for lock-free datastructures in Rust: https://aturon.github.io/blog/2015/08/27/epoch/
sanderjd · 2015-05-19
All the other comments are right, and in Rust this is referred to as "the builder pattern", and is used quite commonly. Here's a guidelines link[0] describing it in more detail.
[0]: https://aturon.github.io/ownership/builders.html
duped · 2025-08-22
> You simply can not do it with state machines polled in user code
That's not really true. The only guarantees in Rust futures are that they are polled() once and must have their Waker's wake() called before they are polled again. A completion based future submits the request on first poll and calls wake() on completion. That's kind of the interesting design of futures in Rust - they support polling and completion.
The real conundrum is that the futures are not really portable across executors. For io_using for example, the executor's event loop is tightly coupled with submission and completion. And due to instability of a few features (async trait, return impl trait in trait, etc) there is not really a standard way to write executor independent async code (you can, some big crates do, but it's not necessarily trivial).
Combine that with the fact that container runtimes disable io_uring by default and most people are deploying async web servers in Docker containers, it's easy to see why development has stalled.
It's also unfair to mischaracterize design goals and ideas from 2016 with how the ecosystem evolved over the last decade, particularly after futures were stabilized before other language items and major executors became popular. If you look at the RFCs and blog posts back then (eg: https://aturon.github.io/tech/2016/09/07/futures-design/) you can see why readiness was chosen over completion, and how completion can be represented with readiness. He even calls out…
staticassertion · 2019-08-15
> Async+Await+Futures isn't needed at all
Define "needed" ? Code with async/await is radically simpler compared to without - this is not just basic sugar but really, really important due to rust's borrow semantics There is code I have written that required Rc/RefCell ceremony to get around the borrowchecker that will be completely handled by async/await.
You can read more about this here:
https://aturon.github.io/tech/2018/04/24/async-borrowing/
> performs worse than a basic epoll loop
There are open issues and afaik all of these are solvable problems with known/ theorized solutions.
> is more confusing, and less able to handle complex flow
Sorry, that's absolutely just not the case Even if "confusing" is subjective, you can not tell me that writing complex loops/ control flow is easier in futures than in async/await. Just look at the examples here:
https://docs.rs/dtolnay/0.0.4/dtolnay/macro._01__await_a_minute.html
simag · 2019-05-15
Kudos!
When Rust 1.0 was announced I had a look. I was very surprised because that language was very different from my previous look, when Rust still had GC and green threads (and a syntax with mystic sigils).
Rust 1.0 looked like it could be a good language, but coming from mainstream languages with a richer ecosystem -- such as Java/Scala or C# --, Rust lacked many common libs. For instance, a high-level approach to non-blocking IO, which is something I need when writing servers. There were other issues -- lexical lifetimes often meant one needed to jump through hoops to please the borrow checker. I thought Rust would need a lot more time to mature enough to be a serious contender in my PL list. The next year, the Zero-Cost Futures post[1] by Aaron Turon showed up in my news feed. It seemed interesting, but it was only a plan. A few months later Tokio was born and, again, it seemed interesting. But there's no way it was ready, was there? I went back to business as usual. I kept hearing about Rust, but I had no intention to use it in the immediate future.
Last year, I was offered a full-time Rust job out of the blue (because of my experience in building distributed systems; I had to learn Rust as a part of the job). I was interested because, in general, I was looking for a change -- but I also wanted to make sure I wouldn't spend energy on a language that wouldn't be relevant in 10 years (at least, according to my intuition). I've had job offers in other emerging…