Series: The Rust Annals

Vol. I Issue 74 nlopes.dev

Announcing Rust 1.73.0

Routine monthly release focusing on standard library ergonomics, integer math methods, and panic message formatting without core language or ecosystem impact.

Cleaner panic messages

The output produced by the default panic handler has been changed to put the panic message on its own line instead of wrapping it in quotes. This can make panic messages easier to read, as shown in this example:

fn main() {
    let file = "ferris.txt";
    panic!("oh no! {file:?} not found!");
}
Output before Rust 1.73:
thread 'main' panicked at 'oh no! "ferris.txt" not found!', src/main.rs:3:5
Output starting in Rust 1.73:
thread 'main' panicked at src/main.rs:3:5:
oh no! "ferris.txt" not found!

This is especially useful when the message is long, contains nested quotes, or spans multiple lines.

Additionally, the panic messages produced by assert_eq and assert_ne have been modified, moving the custom message (the third argument) and removing some unnecessary punctuation, as shown below:

fn main() {
    assert_eq!("🦀", "🐟", "ferris is not a fish");
}
Output before Rust 1.73:
thread 'main' panicked at 'assertion failed: `(left == right)`
 left: `"🦀"`,
right: `"🐟"`: ferris is not a fish', src/main.rs:2:5
Output starting in Rust 1.73:
thread 'main' panicked at src/main.rs:2:5:
assertion `left == right` failed: ferris is not a fish
 left: "🦀"
right: "🐟"

Thread local initialization

As proposed in RFC 3184, LocalKey<Cell<T>> and LocalKey<RefCell<T>> can now be directly manipulated with get(), set(), take(), and replace() methods, rather than jumping through a with(|inner| ...) closure as needed for general LocalKey work. LocalKey<T> is the type of thread_local! statics.

The new methods make common code more concise and avoid running the extra initialization code for the default value specified in thread_local! for new threads.

thread_local! {
    static THINGS: Cell<Vec<i32>> = Cell::new(Vec::new());
}

fn f() {
    // before:
    THINGS.with(|i| i.set(vec![1, 2, 3]));
    // now:
    THINGS.set(vec![1, 2, 3]);

    // ...

    // before:
    let v = THINGS.with(|i| i.take());
    // now:
    let v: Vec<i32> = THINGS.take();
}

3184 contributors to this release.

Reproduced from the Rust blog under its publication licence. Typeset in Literata.