In July, I described a way to make pinning more ergonomic by integrating it more fully into the language. Last week, I develoepd that idea further with the notion of UnpinCell: a wrapper type that lets a user take an &pin mut UnpinCell and produce an &mut T, similar to how other cells let a user take a shared reference to the cell and produce a...
A variation on my previous design for pinned places has occurred to me that would be more consistent with Rust’s existing feature set. The most outlandish aspect of the previous design was the notion of “pinned fields,” which support pinned projection. This is quite different from how field projection normally works in Rust: if you have a mutable...
In the previous post, I described the goal of Rust’s Pin type and the history of how it came to exist. When we were initially developing this API in 2018, one of our explicit goals was the limit the number of changes we would make to Rust, because we wanted to ship a “minimum viable product” of async/await syntax as soon as possible. This meant...
The Pin type (and the concept of pinning in general) is a foundational building block on which the rest of the the Rust async ecosystem stands. Unfortunately, it has also been one of the least accessible and most misunderstood elements of async Rust. This post is meant to explain what Pin achieves, how it came to be, and what the current problem...
This post is meant as an explainer about how substructural type theory can be applied in programming language design. Terms like “substructural type theory” tend to scare and confuse programmers who don’t write Haskell on the weekends, so one thing programming language designers should do when thinking about how they will present their language...
In a high-level language, the programmer is deprived of the dangerous power to update his own program while it is running. Even more valuable, he has the power to split his machine into a number of separate variables, arrays, files, etc.; when he wishes to update any of these he must quote its name explicitly on the left of the assignment, so...
For the past few months I’ve been mulling over some things that Russell Johnston made me realize about the relationship between effect systems and coroutines. You can read more of his thoughts on this subject here, but he made me realize that effect systems (like that found in Koka) and coroutines (like Rust’s async functions or generators) are...
This is a brief note about the definition of iterator.
One problem with the design of async Rust is what do about async clean-up code. Consider that you have a type representing some object or operation (like an async IO handle) and it runs clean up code when you are done using it, but that clean up code itself is also non-blocking and could yield control. Async Rust has no good way to handle this...
In my previous post, I wrote about the distinction between “multi-task” and “intra-task” concurrency in async Rust. I want to open this post by considering a common pattern that users encounter, and how they might implement a solution using each technique. Let’s call this “sub-tasking.” You have a unit of work that you need to perform, and you...
In the early-to-mid 2010s, there was a renaissance in languages exploring new ways of doing concurrency. In the midst of this renaissance, one abstraction for achieving concurrent operations that was developed was the “future” or “promise” abstraction, which represented a unit of work that will maybe eventually complete, allowing the programmer...
Last week, Tyler Mandry published an interesting post about a problem that the Rust project calls “Barbara battles buffered streams.” Tyler does a good job explaining the issue, but briefly the problem is that the buffering adapters from the futures library (Buffered and BufferUnordered) do not interact well with for await if the processing in...
When we developed the Pin API, our vision was that “ordinary users” - that is, users using the “high-level” registers of Rust, would never have to interact with it. We intended that only users implementing Futures by hand, in the “low-level” register, would have to deal with that additional complexity. And the benefit that would accrue to all...
I wanted to follow up my previous post with a small note elaborating on the use of coroutines for asynchrony and iteration from a more abstract perspective. I realized the point I made about AsyncIterator being the product of Iterator and Future makes a bit more sense if you also consider the “base case” - a block of code that is neither...
In my previous post, I said that the single best thing the Rust project could do for users is stabilize AsyncIterator. I specifically meant the interface that already exists in the standard library, which uses a method called poll_next. Ideally this would have happened years ago, but the second best time would be tomorrow. The main thing holding...
Four years ago today, the Rust async/await feature was released in version 1.39.0. The announcement post says that “this work has been a long time in development – the key ideas for zero-cost futures, for example, were first proposed by Aaron Turon and Alex Crichton in 2016”. It’s now been longer since the release of async/await than the time...
Async/await syntax in Rust was initially released to much fanfare and excitement. To quote Hacker News at the time: This is going to open the flood gates. I am sure lot of people were just waiting for this moment for Rust adoption. I for one was definitely in this boat. Also, this has all the goodness: open-source, high quality engineering,...
I want to address a controversy that has gripped the Rust community for the past year or so: the choice by the prominent async “runtimes” to default to multi-threaded executors that perform work-stealing to balance work dynamically among their many tasks. Some Rust users are unhappy with this decision, so unhappy that they use language I would...
I want to wrap up my consideration of the idea of adding new auto traits to Rust with some notes from a conversation I had with Ariel Ben-Yehuda. You can read these two previous posts for context: Changing the rules of Rust Follow up to “Changing the rules of Rust”
In my previous post, I described the idea of using an edition mechanism to introduce a new auto trait. I wrote that the compiler would need to create an “unbreakable firewall” to prevent using !Leak types from the new edition with code from the old edition that assumes values of all types can be leaked. The response has been pretty optimistic...
In Rust, there are certain API decisions about what is and isn’t sound that impact all Rust code. That is, a decision was made to allow or not allow types which have certain safety requirements, and now all users are committed to that decision. They can’t just use a different API with different rules: all APIs must conform to these rules. These...
One of the most famous anecdotes that forms the basis of the United States’ political self-identity is the story of an interaction between Benjamin Franklin and Elizabeth Willing Powel after the Constitutional Convention of 1787, which established the United States’ present form of government. Powel asked Franklin what sort of government the U.S....
I have been devoting a lot of my free time in the past month to thinking about structured concurrency, and a blog post about that is coming soon, but first I want to revisit iterators and generators. In a previous post, I wrote about one of the hardest problems for generators: self-referential generators. Unlike the Future trait when we were...
This is the first post in a series of posts about concurrency in Rust, and the different APIs that can exist to support it. Unlike my recent series on control-flow effects, this series isn’t driving toward any particular vision of what I think the Rust project should do. Instead, I am just trying to publicly explore the problem space and build...
One of the main emphases of my recent posts has been that I believe shipping generators would solve a lot of user problems by making it easy to write imperative iterative code, and especially to make that iterative code interact well with asynchrony and fallibility as well. One thing that frustrates me about the situation is that generators have...
In a previous post, I established the notion of “registers” - code in Rust can be written in different registers, and it’s important to adequately support all registers. I specifically discussed the low-level interface of the AsyncIterator trait, about which there is currently a debate. The interface it currently has is a method called poll_next,...
The previous two posts in this series tried to discuss the design of Rust through the lens of some higher level language concepts: First, the notion that programming languages have different registers Second, the idea that not all patterns should be made into abstractions This post does not introduce any such high-minded concept. It is entirely...
This is the second post in an informal series commenting on the design of async Rust in 2023. In my previous post, after a discussion of the “registers” in which control-flow effects could be handled in Rust, I promised to turn my attention to recent proposals around a concept called “keyword generics.” For reference, there are two posts by the...
It’s been nearly two and half years since I was an active contributor to the Rust project. There are some releases that I’ve been very excited about since then, and I’m heartened by Niko’s recent blog post emphasizing stability and polish over grand new projects. But I’ve also felt a certain apprehension at a lot of the directions the project has...
In the previous post in this series, I wrote about how the core state machine of ringbahn is implemented. In this post I want to talk about another central concept in ringbahn: “drivers”, external libraries which determine how ringbahn schedules IO operations over an io-uring instance.
A bit over a year ago, I wrote some notes on a “smaller Rust” - a higher level language that would take inspiration from some of Rust’s type system innovations, but would be simpler by virtue of targeting a domain with less stringent requirements for user control and performance. During my time of unemployment this year, I worked on sketching out...
Today I made a new release of the iou library, which contains idiomatic Rust bindings to the liburing library. This library allows users to manipulate the new io-uring interface for asynchronous IO on Linux. For more context, you can read my previous post on the first release of iou last year. This new release greatly expands the API of iou,...
I’ve just released a new crate called propane, which is a library for writing generator functions. It can only run on nightly: #![feature(generators, generator_trait, try_trait)] #[propane::generator] fn fizz_buzz() -> String { for x in 1..101 { match (x % 3 == 0, x % 5 == 0) { (true, true) => yield String::from("FizzBuzz"), (true, false) =>...
It’s hard to believe that its been more than 3 years since I opened RFC 2000, which defined the const generics for Rust. At the same time, reading the RFC thread, there’s also been a huge amount of change in this area: for one thing, at the time the RFC was written, const fns weren’t stable, and consts weren’t even being evaluated using miri yet....
Last time I wrote about ringbahn, a safe API for using io-uring from Rust. I wrote that I would soon write a series of posts about the mechanism that makes ringbahn work. In the first post in that series, I want to look at the core state machine of ringbahn which makes it memory safe. The key types involved are the Ring and Completion types.
While implementing ringbahn, I introduced at least two bugs that caused memory safety errors, resulting in segfaults, allocator aborts, and bizarre undefined behavior. I’ve fixed both bugs that I could find, and now I have no evidence that there are more memory safety issues in the current codebase (though that doesn’t mean there aren’t, of...
This is just a note on getting the best performance out of an async program. The point of using async IO over blocking IO is that it gives the user program more control over handling IO, on the premise that the user program can use resources more effectively than the kernel can. In part, this is because of the inherent cost of context switching...
In my previous post, I discussed the new io-uring interface for Linux, and how to create a safe API for using io-uring from Rust. In the time since that post, I have implemented a prototype of such an API. The crate is called ringbahn, and it is intended to enable users to perform IO on io-uring without any risk of memory unsafety.
Last fall I was working on a library to make a safe API for driving futures on top of an an io-uring instance. Though I released bindings to liburing called iou, the futures integration, called ostkreuz, was never released. I don’t know if I will pick this work up again in the future but several different people have started writing other...
In a previous post, I shortly discussed the concept of “effects” and the parallels between them. In an unrelated post since then, Yosh Wuyts writes about the problem of trying to write fallible code inside of an iterator adapter that doesn’t support it. In a previous discussion, the users of the Rust Internals forum hotly discuss the notion of...
I’ve long been a proponent of having some sort of syntax in Rust for writing functions which return results which “ok-wrap” the happy path. This is has also always been a feature with very vocal, immediate, and even emotional opposition from many of our most enthusiastic users. I want to write, in one place, why I think this feature would be...
About two and a half years ago I wrote a Rust library called failure, which quickly became one of the most popular error handling libraries in Rust. This week, its current maintainer decided to deprecate it, a decision I strongly support. This week, I also released a new and very different error-handling library, called fehler. I wanted to...
This is just a post about something that grinds my gears a bit more than it reasonably should: I think the habit of applying for CVEs for Rust (and Rust ecosystem libraries) is silly at best and harmful at worst. I think it muddies the waters about what a vulnerability is, and paints an overly negative picture of Rust’s security situation that...
I’ve just released a new crate called waitmap. This is a concurrent hash map (built on top of dashmap) intended for use as a concurrency primitive with async/await. It extends the API of dashmap by having an additional wait method. The wait future looks up an entry in the map and suspends this task if the entry was not present when wait was...
One of the big sources of difficulty on the async ecosystem is spawning tasks. Because there is no API in std for spawning tasks, library authors who want their library to spawn tasks have to depend on one of the multiple executors in the ecosystem to spawn a task, coupling the library to that executor in undesirable ways. Ideally, many of these...
Today I’m releasing a library called iou. This library provides idiomatic Rust bindings to the C library called liburing, which itself is a higher interface for interacting with the io_uring Linux kernel interface. Here are the answers to some questions I expect that may provoke. What is io_uring? io_uring is an interface added to the Linux...
The first version of async/await syntax is in the beta release, set to be shipped to stable in 1.39 on November 7, next month. There are a wide variety of additional features we could add to async/await in Rust beyond what we’re shipping in that release, but speaking for myself I know that I’d like to pump the breaks on pushing forward big ticket...
Many people who use Rust for a bit - especially those who like the language but do not fall in love with it - feel a sense that there must be a smaller, simpler variation on the same theme which would maybe be a little less powerful, but would also be much easier to use. I agree with them, but I think they are almost always wrong about what would...
In my previous post I said that the lang team would be making our final decision about the syntax of the await operator in the May 23 meeting. That was last Thursday, and we did reach a decision. In brief, we decided to go forward with the preliminary proposal I outlined earlier: a postfix dot syntax, future.await. For more background, in...
The idea of a zero cost abstraction is very important to certain programming languages, like Rust and C++, which intend to enable users to write programs with excellent performance profiles with relatively little effort. Since this idea is fundamental to the design of Rust and my work, I want to investigate, for a moment, what exactly a zero cost...
This is an announcement regarding the resolution of the syntax for the await operator in Rust. This is one of the last major unresolved questions blocking the stabilization of the async/await feature, a feature which will enable many more people to write non-blocking network services in Rust. This post contains information about the timeline for...
The biggest unresolved question regarding the async/await syntax is the final syntax for the await operator. There’s been an enormous amount of discussion on this question so far; a summary of the present status of that discussion and the positions within the language team is coming soon. Right now I want to separately focus on one question which...
This is my second post on the design of generators. In the first post, I outlined what an MVP of the feature would look like. In this post, I want to take a look at the first design issue for the feature: how it integrates with the ? operator. To explain exactly what I mean, let’s start with a specific motivating example: // This generator yields...
We’re still not finished with the design of async/await, but it’s already become clear that it’s time to get the next phases of the feature into the pipeline. There are two extensions to the minimal async/await feature we’ve currently got that seem like the clear high priority: Async methods: allowing async fn to be used in traits. Generators:...
In the previous post, I provided a lot of background on what the waker API is trying to solve. Toward the end, I touched on one of the tricky problems the waker API has: how do we handle thread safety for the dynamic Waker type? In this post, I want to look at that in greater detail: what we’ve been doing so far, and what I think we should do.
Work on supporting async/await in Rust continues to progress rapidly. I’m hoping to write a retrospective on everything that happened in 2018 in a few weeks. Right now we’re closing in on an important milestone: stabilizing the futures API that will be used to interact programmatically with asynchronous computations. The biggest remaining area of...
We all know that classic aphorism: Year comes to an end, Rust blog post press send. This is mine. There are lots of cool technical improvements to Rust that I want the project to achieve this year, and a few in particular that I’m definitely going to be putting a lot of time into. But this blog post is going to talk about none of them. Instead, I...
This blog post is about a project called Romio that I’ve been working on over the past two or three weeks. Romio is a port of a small part of the Tokio project to the newer futures APIs. I started the project to get some experience porting code from the old futures API to the new API. However, we realized that this code could also be useful to...
One thing we’ve left as an unresolved question so far in the matter of async/await syntax is the exact final syntax for the await operation. In the current implementation, awaits are written using a compiler plugin: async fn foo() { await!(bar()); } This is not because of any technical limitation: the reason we have done this is that we have not...
Rust 2018 is almost out the door, but there is one big decision the language team has yet to make. It has to do with the modules and paths system, so of course it is a very easy decision that no one has a strong opinion about. ;-) In Rust 2018, we’ll be making some big changes to how paths work to try to create a more consistent experience. The...
The post before this one covered how shifgrethor handles rooting: how we track for the garbage collector that this object is alive. That isn’t sufficient for implementing a tracing garbage collector though: the idea of a tracing garbage collector is that we can trace from rooted objects through all of the objects they reference. That way, instead...
After the digression in the previous post, it’s time to get back to what I promised in the first post: a look at how shifgrethor handles rooting. Shifgrethor’s solution is somewhat novel and takes advantage of some of Rust’s specific features, so I want to start by looking briefly at some of the other options. How to root a GC’d object There are...
In the previous post I said that in the second post in the series we’d talk about how rooting works. However, as I sat down to write that post, I realized that it would be a good idea to back up and give an initial overview of how a tracing garbage collector works - and in particular, how the underlying garbage collector in shifgrethor is...
Evan Czaplicki, the creator and maintainer of the Elm project (a project that I love by the way) gave a great talk at Strange Loop last month called “The Hard Parts of Open Source.” I really enjoyed and valued this talk, and I encourage everyone who is involved in open source to watch it. You can find on YouTube here. In particular, I got a lot...
I’m really excited to share with you an experiment that I’ve been working on for the past 5 or 6 weeks. It’s a Rust library called shifgrethor. shifgrethor implements a garbage collector in Rust with an API I believe to be properly memory safe. I’ll be going through all of the technical details in future blog posts, so I want to kick this series...
Today I realized a new crate called pin-cell. This crate contains a type called PinCell, which is a kind of cell that is similar to RefCell, but only can allow pinned mutable references into its interior. Right now, the crate is nightly only and no-std compatible. How is the API of PinCell different from RefCell? When you call borrow_mut on a...
There are 2 hard problems in computer science: cache invalidation, naming things, and off-by-1 errors. Naming a project, tool, or concept that you want other people to use is a very hard problem. The most important thing, of course, is that the name sounds cool. Then, significantly less important, but still quite important, is that the name...
A few months ago we introduced the concept of “pinned” references - pointers which “pin” the data they refer to in a particular memory location, guaranteeing that it will never move again. These are an important building block for certain patterns that had previously been hard for Rust to handle, like self-referential structs and intrusive lists,...
Recently, I wrote a little a side project to sign git commits without gpg. When I did this, I decided to use the Rust 2018 edition. I also transitioned an existing library from Rust 2015 to Rust 2018 to see how that tooling worked. I thought I’d write a blog post about my experience using the Rust 2018 preview and the state of things right now....
Unlike most git users, I try to sign my commits. Unfortunately, the only way to do this right now is to use PGP signatures, because that is all that git is able to integrate with. This has meant that in practice I have to use GPG if I want to sign my commits, an experience I do not relish. Last week, I wrote a program to replace GPG for that...
Last time, we introduced the idea of async methods, and talked about how they would be implemented: as a kind of anonymous associated type on the trait that declares the method, which corresponds to a different, anonymous future type for each implementation of that method. Starting this week we’re going to look at some of the implications of...
Async/await continues to move along swimmingly. We’ve accepted an RFC describing how the async/await syntax will work in Rust, and work is underway on implementing support for it in the compiler. We’re hopeful that users will be able to start experimenting with the syntax on nightly by early July. The RFC for async/await didn’t address one...
I’m really excited to announce the culmination of much of our work over the last four months: a pair of RFCs for supporting async & await notation in Rust. This will be very impactful for Rust in the network services space. The change is proposed as two RFCs: RFC #2394: which adds async & await notation to the language. RFC #2395: which moves a...
It’s hard to believe its been almost 6 weeks since the last post I made about async/await in Rust. So much has happened that these last several weeks have flown by. We’ve made exceptionally good progress on solving the problem laid out in the first post of this series, and I want to document it all for everyone. Future and the pinning API Last...
I’m planning to release a 1.0.0 version of failure on March 15. Once this happens, I don’t plan to release any further breaking changes to the failure crate (though maybe someday in the distant future). Breaking changes in 1.0 failure is in a somewhat unique position as being a significant part of the public API of other libraries that depend on...
Two posts ago I proposed a particular interface for shipping self-referential generators this year. Immediately after that, eddyb showed me a better interface, which I described in the next post. Now, to tie everything together, its time to talk about how we can integrate this into the futures ecosystem. Starting point: this Generator API To...
I did not plan to write this blog post. I thought that the fourth post in my series would explain how we could go from the generator API in my previous post to a futures API in which you don’t have to heap allocate every async call. But eddyb surprised me, and now I have to revisit the API in the previous post, because we can implement everything...
In the first post, we looked at the relationship between generators and a more general notion of self-references. In the second post, we narrowed down exactly what problem we need to solve to make generators work, and talked about some solutions that we’ve considered but don’t feel like we could ship in the near future. In the original post, I...
Last time we talked about the broader problem that generators with references across yield points represent: self-referential structs. This time, I want to narrow in on the specific problem that needs to be solved to make generators work, and also discuss some ideas for solutions that I think are false starts. (I still don’t have a proposal about...
This is the first in a series of blog posts about generators, async & await in Rust. By the end of this series, I will have a proposal for how we could expediently (within the next 12 months) bring generators, async & await to stable Rust, and resolve some of the most difficult ergonomics problems in the futures ecosystem. But that proposal is...
Hi :) I’ve been working on a project called configure, which is intended to create a uniform way to load configuration variables from the environment of the program. Specifically, the goal is to create something that libraries can rely on to allow applications to delegate decisions about how configuration is loaded to applications, without those...
The Rust project has requested blog posts about the project’s goals for 2018. I found myself in pretty much complete agreement with Nick Cameron’s post, so I thought instead I would write about my own personal goals for Rust in 2018. I am fortunate enough to work on Rust full-time; modulated by the work that needs to get done to accomplish larger...
Unsafety in Rust is often discussed in terms the primitive operations that can only be performed inside of unsafe blocks (such as dereferencing raw pointers and accessing mutable statics). I want to look at it from a different angle from these primitive operations, and instead focus on the capability to produce unsafe abstractions. The general...
Oftentimes when I am conversing about the design of Rust with other users - as on RFCs or the internals forum - I witness a peculiar remark about “explicitness.” It usually goes something like this: I do not like Feature Design X because it is too implicit. Magic is okay in Other Language Y, but Rust is supposed to be an explicit language, so we...
I’ve just published failure 0.1.1 to crates.io. It’s mostly some incremental improvements to failure that have been suggested since the first release two weeks ago. Improvements to the derive A big change in version 0.1.1 is that the derive can be used without depending on the failure_derive crate separately. All that needs to be done is tagging...
I’m really excited to announce a new crate I’ve been working on, called failure, and which I’ve just released to crates.io. Failure is a Rust library intended to make it easier to manage your error types. This library has been heavily influenced by learnings we gained from previous iterations in our error management story, especially the Error...
cargo gained a new feature this week! You can now download dependencies from alternative registries, alongside the dependencies you download from crates.io. This is an important step in enabling organizations to distribute their internal libraries through cargo without requiring them to upload those libraries to a public registry. This feature...
Previously, I attempted to maintain a blog using GitHub Pages. I was very unsuccessful at actually producing blog posts, though. I don’t care a lot about the appearance or maintenance of my blog site. What I want from the experience is the same experience I have writing Rust RFCs (because I have a lot of experience doing that): I write some...
The problem: defining a ‘handshake’ protocol between two traits You have a problem that decomposes in this way: you want any type which implements trait Alpha to be composable with any type which implements trait Omega… That is, if Foo and Bar are both Alphas and Baz and Quux are both Omegas, you can compose Foo with Baz or Quux, and the same...
A while ago I was considering an idea, so I wrote a tweet to ask what folks thought about it. A very spirited discussion followed about the Rust module system and what the pain points with it were (indeed - whether or not there were pain points at all). Depending on your skill at navigating Twitter’s UI, you may or may not be able to read the...