Without boats, dreams dry up The previous two posts in this series tried to discuss the design of Rust through the lens of some
higher level language concepts: This post does not introduce any such high-minded concept. It is entirely down in the weeds. That’s
partly because it is based on content I removed from the previous post so that post could focus on
the higher point. 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 current design team of Rust that are
my reference point for this commentary: I’m not going to reiterate these blog posts at length, but in brief “keyword generics” is a proposal
to introduce a new kind of abstraction to Rust, to allow types to be abstracted over certain
effects. The examples have focused on 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 taken, which has often occupied my thoughts.
From that preoccupation this blog post has emerged, hopefully the first in a series over the next
few weeks outlining my thoughts on the design of Rust in 2023, especially in connection to async,
and I hope its impact will be chiefly positive. 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 what a language like that would
look like in a bit more detail. I wanted to write a bit about what new conclusions I’ve come to
during that time. 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, introduces some valuable improvements, and contains
some breakages. I figured I would let this blog post serve as some basic release notes. I’ve just released a new crate called propane, which is a library for writing generator functions. It can only run on nightly: 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. There’s been a lot of work over the
years on the const generics feature, but still nothing has shipped. However, I think we have defined
a very useful subset of const generics which is stable enough to ship in the near term. 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 course). I wanted to write about both of
these bugs, because they had an interesting thing in common: they were both caused by destructors.Const as an auto trait
Patterns & Abstractions
async
and const
as the effects, but there is sometimes
discussion of try
as well. Astute readers will notice this is an overlapping but not identical set
of effects to the effects I identified in my last post; I did not mention const
as an effect, and
as far as I know the keyword generics working group has not devoted much or any time to considering
iteration as an effect.The registers of Rust
Ringbahn III: A deeper dive into drivers
Revisiting a 'smaller Rust'
iou version 0.3 released
Propane: an experimental generator syntax for Rust
#![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) => yield String::from("Fizz"),
(false, true) => yield String::from("Buzz"),
(..) => yield x.to_string(),
}
}
}
Shipping Const Generics in 2020
Ringbahn II: the central state machine
Two Memory Bugs From Ringbahn