5 Game-Changing Updates in Rust 1.95.0

<p>Rust 1.95.0 has arrived, and it's packed with features that elevate the language's expressiveness, safety, and performance. Whether you're a systems programmer or a web developer, these five updates—from a new compile-time macro to enhanced standard library capabilities—will simplify your code and unlock new patterns. Let's dive into what makes this release special.</p> <h2 id="item1">1. The <code>cfg_select!</code> Macro: Compile-Time Branching Reimagined</h2> <p>Rust 1.95 introduces <code>cfg_select!</code>, a macro that acts like a compile-time <code>match</code> for configuration predicates. It expands to the right-hand side of the first arm whose condition evaluates to <code>true</code>. This eliminates the need for the popular third-party <code>cfg-if</code> crate in many cases. For example:</p><figure style="margin:20px 0"><img src="https://www.rust-lang.org/static/images/rust-social-wide.jpg" alt="5 Game-Changing Updates in Rust 1.95.0" style="width:100%;height:auto;border-radius:8px" loading="lazy"><figcaption style="font-size:12px;color:#666;margin-top:5px">Source: blog.rust-lang.org</figcaption></figure> <pre><code>cfg_select! { unix => { fn foo() { /* unix specific */ } } target_pointer_width = "32" => { fn foo() { /* 32-bit */ } } _ => { fn foo() { /* fallback */ } } } let os = cfg_select! { windows => "windows", _ => "not windows", };</code></pre> <p>This macro supports arbitrary cfg predicates and a wildcard <code>_</code> arm. Its syntax is cleaner and more flexible than nested <code>#[cfg]</code> attributes, making platform-specific code more readable. It's particularly useful for library authors who need to support multiple targets without messy conditionals.</p> <h2 id="item2">2. If-let Guards in Match Expressions: Pattern Matching on Steroids</h2> <p>Building on the let chains stabilised in Rust 1.88, version 1.95 brings <code>if let</code> guards to <code>match</code> arms. This lets you combine pattern matching with additional conditions that themselves involve pattern matching. For example:</p> <pre><code>match value { Some(x) if let Ok(y) = compute(x) => { println!("{}, {}", x, y); } _ => {} }</code></pre> <p>The guard <code>if let Ok(y) = compute(x)</code> succeeds only when <code>compute(x)</code> returns <code>Ok</code>, binding the inner value to <code>y</code>. Note that the compiler currently does not consider these guards in exhaustiveness checking—a known limitation that may be improved in future releases. This feature enables more concise and expressive handling of nested results or options.</p> <h2 id="item3">3. <code>MaybeUninit</code> and <code>Cell</code> Array Conversions: Safer Zero-Cost Abstractions</h2> <p>Several trait implementations for <code>MaybeUninit</code> and <code>Cell</code> arrays are now stable, making it easier to convert between arrays of uninitialised values and single <code>MaybeUninit</code> arrays, and to get array references from <code>Cell</code> slices. For instance:</p> <ul> <li><code>MaybeUninit&lt;[T; N]&gt;: From&lt;[MaybeUninit&lt;T&gt;; N]&gt;</code></li> <li><code>Cell&lt;[T; N]&gt;: AsRef&lt;[Cell&lt;T&gt;; N]&gt;</code> and <code>AsRef&lt;[Cell&lt;T&gt;]&gt;</code></li> <li><code>bool: TryFrom&lt;{integer}&gt;</code> for safe conversion.</li> </ul> <p>These additions reduce the need for unsafe code when working with uninitialised memory or interior mutability. They enable safe, ergonomic patterns for low-level data structures, while maintaining Rust's zero-cost abstraction promise. The <code>TryFrom</code> implementation for <code>bool</code> provides a fallible way to convert integers to booleans, catching invalid values at runtime.</p> <h2 id="item4">4. Atomic Operations Get <code>update</code> and <code>try_update</code> Methods</h2> <p>Atomic types like <code>AtomicPtr</code>, <code>AtomicBool</code>, and the integer atomics now provide <code>update</code> and <code>try_update</code> methods. These allow you to atomically modify the value using a closure, similar to <code>fetch_update</code> but with a more ergonomic interface. For example:</p> <pre><code>use std::sync::atomic::{AtomicU32, Ordering}; let counter = AtomicU32::new(0); counter.update(|x| x + 1, Ordering::SeqCst);</code></pre> <p>The <code>update</code> method loops until the operation succeeds, while <code>try_update</code> attempts once and returns <code>Err</code> if the CAS fails. These methods simplify concurrent programming by reducing boilerplate. They are available on all stable atomic types (except <code>AtomicBool</code> for <code>update</code>/<code>try_update</code>—it uses a slightly different signature). This enhancement makes lock-free algorithms more accessible.</p> <h2 id="item5">5. <code>core::range</code> Module and Collection Convenience Methods</h2> <p>Rust 1.95 stabilises the <code>core::range</code> module, which includes types for range expressions: <code>RangeInclusive</code> and <code>RangeInclusiveIter</code>. These provide more flexibility when working with inclusive ranges. Additionally, several collections gain <em>mutable</em> insertion and push methods:</p> <ul> <li><code>Vec::push_mut</code> and <code>Vec::insert_mut</code></li> <li><code>VecDeque::push_front_mut</code>, <code>push_back_mut</code>, and <code>insert_mut</code></li> <li><code>LinkedList::push_front_mut</code></li> </ul> <p>These methods return a mutable reference to the inserted element, enabling chainable operations. For example: <code>v.push_mut(item).do_something()</code>. The <code>cold_path</code> hint (<code>core::hint::cold_path</code>) is also stabilised, helping optimisers with branch prediction. Together, these additions improve ergonomics and performance tuning.</p> <p>Rust 1.95.0 is available now via <code>rustup update stable</code>. If you haven't installed Rust yet, head to <a href="https://rustup.rs">rustup.rs</a> to get started. For a complete list of changes, see the <a href="https://github.com/rust-lang/rust/blob/stable/RELEASES.md">detailed release notes</a>. Happy coding!</p>
Tags: