RustConf 2023

Here are my notes from 🦀 RustConf 2023 🦀. With no ado:

# Talks

All RustConf talks were 30 minutes, with no live Q&A. Instead, a channel on the Discord server was opened for each talk where the speaker and curious attendees would go to ask and answer questions. It had the same character as the in-person circle that sometimes forms around a speaker after a talk.

At only 30 minutes, the talks flew by, so I tried to focus on the material. As a result, my notes below skip a most of the content of each talk.

Once videos are posted online, I’ll update this post with links.


# Rustacean Community Interfaces

Nell Shamrell-Harrington

A survey of avenues for Rustacean to get involved. This was a nice way to start the conference.

The talk featured a bonus plea for sanity on the topic of drama and criticism. A recurring undercurrent of this opening talk, the closing keynote, and places in between, were the recent drama(s) with the Rust Foundation, Conf, and Project. Attendees lucky enough to have missed these various dramas may have felt a little lost at times. My take is that criticism is an essential part of any healthy system of humans, but criticism spread by social media goes rancid quickly, causing harm to users, contributors, and Rust itself. We don’t have to keep paying this opportunity cost.

With that in mind, this slide of Nell’s rang true.

unsafe {
  discuss_on_social_media();
}

Nell also mentioned rfcbot.rs which was new to me. I plan to check the open RFCs periodically to see what interesting changes may be coming to the language.


# The standard library is special. Let’s change that.

Jacob Pratt

Jacob walked through quite a few proposed changes to the standard library. Most were outside my experience, but two stood out: stability attributes and custom preludes.

Stability attributes

Currently only the standard library is allowed to use stability attributes, which allow (standard) library authors to annotate the stability of various parts of the API.

#[stable(feature = "foo", since = "1.420.69")]

// or

#[unstable(feature = "foo", issue = "1234", reason = "lorem ipsum")]

Extending this ability to all library crates seems like a win-win to me.

Custom preludes

Unless you’re in the #[no_std] club, the standard library’s prelude is included for you by default. Other crates cannot define automatic preludes, and have adopted the convention of exporting a prelude module which can be included with use some_crate::prelude::*;.

Note: originally this section incorrectly stated that the proposal would allow crates to create preludes that could only be disabled by opting out. That was corrected by Jacob and the rest of the section has been rewritten.

If I understood this custom prelude proposal correctly, it would allow any library crate to define its own prelude and when you depend on it, its custom prelude will be automatically imported into all your modules. To enable a crate’s prelude: some_crate = { version = "1", prelude = true }. In other words, the auto-import of preludes would be opt-in.

There’s another custom prelude RFC in the back catalog: RFC 890. It describes a system where custom preludes can be defined at crate level, so if you do a lot of, say, high-precision math in your application, you could add rust_decimal::prelude::* to your crate’s prelude, and it would be automatically included in all modules. It’s been closed for several years, not for lack of quality but as low priority.


# Extending Rust’s Effect System

Yoshua Wuyts

In rust, values can be genericized. For instance, you’d rarely (never?) need to write a duplicate function for different types of input:

fn foo_i32(n: i32) { ... }
fn foo_u8(n: u8) { ... }
fn foo_string(n: String) { ... }
// etc

Thanks, generics:

fn foo<T>(n: T) { ... }

This talk was about several remaining reasons that functions wind up duplicated. For example, if the function foo could support both sync and async invocation, you’d need two copies of the function.

fn foo() { ... }
async fn foo_async() { ... }

A PL theory buff I am not, and so the idea that async is a member of a set of “effects” was new to me. The effects present in Rust are:

  • async
  • unsafe
  • const
  • try (?)
  • generators (yield)

The term Keyword Generics had crossed my feed several times, and I’ve learned since RustConf that the keyword generics effort morphed into effects work, as more relevant PL theory was uncovered.

The changes proposed would allow writing a function that’s generic over an effect such as. Syntax is not final, but the feature would allow the call site to determine whether the function is being called in sync/async mode.

// define a "maybe async" function (syntax not final)
?async fn foo() { ... }

foo(); // infer sync
foo().await; // infer async
foo::<async>().await; // force async

To me, it seems handy, but the trade-off is probably that the body of the foo function is going to get messy, split down the middle by if I_AM_ASYNC. To keep the function body clean, it would be prudent to split it into two functions anyway, just like is done today. The difference being that the public API could consist of a single function, which perhaps is worth the trade-off.


# Profiling Async Applications in Rust

Vitaly Bragilevsky

I was excited for this one as I’ve been doing a lot of profiling lately. It was full of good information, but the main thing I’ll remember is this rule of thumb:

Prefer tracing to sampling when profiling async code.

Prima facie! It rang true the moment he said it. It makes sense that random sampling is better suited to CPU-intensive, “mostly-on” work, and deterministic tracing is better suited to async, “mostly-off” work.

Here are a few tools Vitaly recommended.

  • futures_diagnose: instruments futures with diagnostics that can be visualized later in Chrome devtools or Perfetto UI
  • tokio_console is another instrumentation option which includes live data viz; live viz is interesting but less useful than longer-term stats and graphs
  • Goose: a rust-based tool for generating load; has its own reporting. “Have you ever been attacked by a goose?”

Vitaly works at JetBrains, and on the first day of the conference, they announced a dedicated Rust IDE, named RustRover. Vitaly also MC’d a very fun Rust quiz each day. My highlight was upon seeing the quiz question “What is the name of the new Rust IDE announced today?”, answering it with “VS Code”. Vitaly pointed at my answer and said “I don’t like that one.” Thinking back on it, an even better answer would have been: “Borland Turbo Rust”


# Beyond Ctrl-C: The Dark Corners of Unix Signal Handling

Rain

This talk was about Unix signals, signal groups, and signal handlers. To summarize it, I would call it: man 7 signal-safety & Rust.

Rain created this example file download program to complement the talk: github.com/sunshowers/rustconf-2023-signals

Tip: tokio::select! can help catch signals in async tokio applications, see this example

After the talk, I asked if there were any testing utilities/frameworks focused on signals. Rain’s answer was No, and my searches didn’t turn up any dedicated signal testing tools. No easy way to test that a given program is a good signal citizen (sigtizen?)? For something so easy to get wrong (signal handling), I was surprised by the lack of testing tools in the 50 years since Unix signals were introduced (signal was introduced in Bell Labs’ Unix Version 4, 1973).

Of course, it’s quite easy to send signals to processes, so testing shouldn’t be hard. In a well-tested program, the tests know something about the state of the application, and are thus well-positioned to send signals at precise times. For instance, SIGTERM mid-way through a file download and test the outcome.

Adding precise signal testing is a lot of work, though, so I started thinking about a signal fuzzer. It would send random signals at random times, and run user-provided checks to ensure invalid states aren’t entered. I’m not sure if I’ll find the time to build it, but it smells useful.


# A Rust-based Garbage Collector for Python

Joannah Nanjekye

Joannah presented on a project that’s part of her PhD research at an IBM lab. The project was to create a Rust-based garbage collector for Python.

MMTk (Memory Management Toolkit) was used for the, well, memory management piece. Being 20 years old, it predates Rust by quite a bit and was originally implemented in Java. Since then, it’s been rewritten in Rust.

Joannah chose to swap out the GC of RPython. If I understood correctly, RPython’s integration points with its GC were cleaner than CPython’s, and thus easier to re-bind to something new.

Much of the work was binding RPython memory events (my word) to MMTk calls. I think she even said the bindings ended up consisting of more code than MMTk itself.

She presented a lot of data about the results, and in many cases it was on-par or faster than the existing GC.


# How Powerful is Const?

Nikolai Vasquez

Short answer: very.

Nikolai covered a wide variety of usages of const, from the basic…

const HOW_POWERFUL_IS_CONST: &str = "Very!";

To compile-time computation in a const block…

const N: usize = {
  let mut n = 0;
  n += 1;
  n
};

To const generics…

struct Stuff<const N: usize> {
    data: [usize; N],
}

And recommended these crates as examples of advanced use of const.

  • const_format - compile-time string formatting
  • condtype - choose types at compile-type via boolean constants
  • impls - determine if a type implements a logical trait expression (see: “Trait-Dependent Type Sizes” if you have a strong stomach)

Nikolai also mentioned divan, a benchmarking crate he’s been working on that will be ready soon (update: it’s released). He didn’t go into detail, but I’m curious what it offers compared to the more established criterion.

I highly recommend this talk for anyone who feels they may not be leveraging const features of Rust enough.


Luke Francl

Luke presented Blackbird, GitHub’s fairly new code search system. It’s implemented in Rust, and has some tight integration points with some established Go programs.

They migrated through three approaches to Rust/Go FFI and the advantages and drawbacks of each are covered in depth. Unfortunately the slides were difficult to read due to the lighting in the room, but once the videos are released the problem will be alleviated, and it will be interesting to review the presentation again.

One key takeaway I gleaned from the approaches they tried was “just let Go manage the memory”.

I had pleasure of running into Luke while checking out of the hotel the next morning and we had a nice chat. Great meeting you, Luke!


# The Art and Science of Teaching Rust

Will Crichton

Will is one of those rare people who can expound at great length, both during and after his presentation, with no hesitative “ums”.

It’s well understood that Rust is not easy to learn, and The Book is generally the best place to start. Any reader of the online Rust Book in the past year or so may have noticed a link at the top to a “more interactive” version at brown.edu. That version of the book is the subject of this talk.

Will (and team?) are on a mission to scientifically answer questions about what parts of Rust are the hardest, and how they can be taught differently for better understanding. They’ve done this by adding interactive quizzes throughout the Rust Book to help readers validate their burgeoning understandings.

More than 1 million quiz questions have been answered since the interactive book launched! As the data started coming in, some low-scoring questions were singled out and small sections of the Book rewritten to improve understanding. The talk goes into specifics and it was very interesting to see.

They’ve also created aquascope, a tool that adds visualizations to Rust source code. It looks really helpful for quickly validating ones assumptions about the effects of lifetimes, aliasing rules, and more.


# Rust in the Wild: A Factory Control System From Scratch

Carter Schultz

This was a very entertaining, feel-good talk.

The premise

We know C++ and Python. We need to build a control system for a brand new recycling factory. It needs to be ready in 6 months. From experience, we know Python won’t be fast enough, and C++ would be riddled with bugs.

The outcome

Carter & co, knowing no Rust, built a factory control system a short time, in Rust. The the full-factory bring-up was the first time the code was fully tested. It was a big success, with loads of performance headroom and no bugs of any consequence.


# Closing Keynote

Elizabeth Ayer

This talk wasn’t about Rust, exactly, since Elizabeth was new to the Rust community. It was more about open development spaces like the Rust world, and was a bit of a callback to the opening talk. I think a fair summary of the thesis is “Open spaces are amazing, but they need small closed spaces within in order to thrive.” It was a fun talk about matters of consequence.


# Tidbits

cargo mutants was written on a white board. It’s a code coverage utility that randomly removes bodies of functions and ensures tests fail as a result.

as/to On some level, I’d absorbed the distinction between the function naming conventions as_ and to_ but hadn’t yet heard it described head-on. The convention is that as_ functions do cheap conversions, usually just recasting (like String::as_str -> &str), whereas to_ functions do more costly conversions.

As with most conferences, the hallway track was just as good as the speaker tracks. Everyone I spoke with was delightful. Most conversations were of the form “Isn’t Rust great? Let us count the ways.” but I also enjoyed hearing about other people’s work. From power grid monitoring in Germany to harmonizing census data at the University of Minnesota, it was fun to hear about spaces Rust is being applied.