● LIVE   Breaking News & Analysis
Oppise Stack
2026-05-02
Technology

Rust 1.95.0: New Macros, Better Pattern Matching, and More

Rust 1.95.0 introduces cfg_select! macro, if-let guards in match, and many stabilized APIs including atomic updates and new collection methods.

Welcome to the latest chapter in Rust's evolution! Version 1.95.0 brings several powerful enhancements that make everyday coding more flexible and expressive. Whether you're managing compile-time configuration with the new cfg_select! macro or writing cleaner pattern-matching logic with if-let guards, this release has something for everyone. In this Q&A, we'll dive into the most exciting features, from new standard library APIs to performance tricks—all explained in a straightforward, engaging way.

What is the new cfg_select! macro and how does it work?

The cfg_select! macro acts like a compile-time match for conditional configuration (cfgs). It expands to the right-hand side of the first arm whose predicate is true, similar to the popular cfg-if crate but with a distinct syntax. For example, you can define platform-specific functions without repeating #[cfg(...)] attributes everywhere:

Rust 1.95.0: New Macros, Better Pattern Matching, and More
Source: blog.rust-lang.org
cfg_select! {
    unix => {
        fn foo() { /* unix specific functionality */ }
    }
    target_pointer_width = "32" => {
        fn foo() { /* non-unix, 32-bit functionality */ }
    }
    _ => {
        fn foo() { /* fallback implementation */ }
    }
}

It also works for expressions, like assigning a string based on the platform. This macro cleans up messy nested cfg! calls and makes conditional compilation far more readable.

How do if-let guards enhance match expressions in Rust 1.95?

Rust 1.88 stabilized let chains, and now version 1.95 brings that power into match arms through if-let guards. This means you can add a pattern-matching condition inside a match arm, making complex destructuring much more concise:

match value {
    Some(x) if let Ok(y) = compute(x) => {
        // Both `x` and `y` are available here
        println!("{}, {}", x, y);
    }
    _ => {}
}

Previously you'd need nested if let or a separate match inside the arm. This new syntax keeps your code linear and readable. Note that the compiler doesn't consider patterns in if-let guards during exhaustiveness checks (just like regular if guards), so you still need a wildcard arm for safety.

What are the key stabilized APIs in Rust 1.95?

A large batch of APIs graduated to stable, especially for MaybeUninit and Cell arrays:

  • MaybeUninit<[T; N]> now supports From, AsRef, and AsMut conversions with [MaybeUninit<T>; N] (and the reverse).
  • Cell<[T; N]> and Cell<[T]> get AsRef implementations for [Cell<T>] slices.
  • bool: TryFrom<{integer}> lets you safely convert integers to booleans.
  • New atomic methods: AtomicPtr::update, AtomicBool::update, AtomicI*::update, AtomicU*::update, and their try_update counterparts.
  • The core::range module now includes RangeInclusive and its iterator.
  • core::hint::cold_path marks a code path as unlikely for branch prediction.
  • New unsafe pointer methods: as_ref_unchecked and as_mut_unchecked for *const T and *mut T.
  • Collection methods: Vec::push_mut, Vec::insert_mut, VecDeque::push_front_mut, VecDeque::push_back_mut, VecDeque::insert_mut, and LinkedList::push_front_mut.

These additions fill important gaps and improve safety ergonomics.

What improvements have been made to atomic operations?

Rust 1.95 adds update and try_update methods to all standard atomic types: AtomicPtr, AtomicBool, AtomicI*, and AtomicU*. update atomically reads the current value, applies a closure, and stores the result—retrying if the value changes under contention. try_update does the same but returns None instead of retrying. This eliminates the boilerplate of manual compare-and-swap loops when you need to modify an atomic cell in a functional style. For example, you can now write atomic_ptr.update(|old| old.wrapping_add(1)) instead of a busy loop.

What are the new mutable methods for Vec, VecDeque, and LinkedList?

Several collection types gained _mut variants of existing insertion methods that take ownership of the element you're adding:

  • Vec::push_mut and Vec::insert_mut allow you to push or insert a mutable reference to a value (requiring the element to be Copy).
  • VecDeque::push_front_mut, VecDeque::push_back_mut, and VecDeque::insert_mut do the same for deques.
  • LinkedList::push_front_mut adds a mutable push to the front of the list.

These methods are especially useful when working with buffers or collections of MaybeUninit cells, where you want to avoid copying or cloning data.

How can I update to Rust 1.95.0?

If you already have Rust installed via rustup, simply run:

rustup update stable

This will fetch the latest stable release (1.95.0) and update your toolchain. If you don't have rustup yet, grab it from the official website. For those who want to help test upcoming features, you can switch to the beta or nightly channels using rustup default beta or rustup default nightly. Remember to report any bugs you find on the Rust issue tracker.