Rust 1.95: cfg_select! joins the standard library and match gets if-let guards
Rust 1.95.0 was released on April 16. If you already have Rust installed through rustup, you upgrade with rustup update stable. It is not a headline-grabbing release, but it brings two language changes that will show up in everyday code and one removal that deserves attention from anyone working with custom targets.
cfg_select!: the cfg-if that became standard
Any Rust project that needs to behave differently per platform ends up reaching for the cfg-if crate. Rust 1.95 stabilizes the cfg_select! macro, which, according to the announcement, works roughly like a compile-time match on cfg predicates. It serves the same purpose as cfg-if, with different syntax, and expands to the right-hand side of the first arm whose predicate is true.
The example from the official post shows both uses, for defining items and as an expression:
cfg_select! {
unix => {
fn foo() { /* unix specific functionality */ }
}
target_pointer_width = "32" => {
fn foo() { /* non-unix, 32-bit functionality */ }
}
_ => {
fn foo() { /* fallback implementation */ }
}
}
let is_windows_str = cfg_select! {
windows => "windows",
_ => "not windows",
};
The _ arm acts as the fallback, which makes the default behavior explicit. I especially like the expression form: picking a value per platform in one line, without duplicating #[cfg] blocks, makes code much more readable. It is one less dependency for many crates.
if-let guards in match
Rust 1.88 stabilized let chains. Version 1.95 brings that capability into match expressions: a guard can now use if let to perform a second pattern match. The example from the announcement:
match value {
Some(x) if let Ok(y) = compute(x) => {
// Both `x` and `y` are available here
println!("{}, {}", x, y);
}
_ => {}
}
Before, this pattern required nesting an if let inside the arm or restructuring the logic. The important caveat, highlighted in the post itself: the compiler does not count patterns in if let guards toward match exhaustiveness, just as with regular if guards. In other words, you still need the catch-all arm.
End of stable support for JSON target specs
Rust 1.95 removes stable support for passing a custom target specification to rustc. According to the team, anyone on a fully stable toolchain should not be affected, because building the standard library, even just core, already required nightly-only features. The team is collecting use cases on a tracking issue to decide whether some form of this feature should be stabilized in the future. If you work on embedded systems or kernels and depend on this, it is worth adding your case there.
Stabilized APIs
The list is long. The highlights, for me:
bool: TryFromfor integers, an explicit and fallible conversion.updateandtry_updatemethods onAtomicPtr,AtomicBooland the integer atomics, which simplify compare-and-swap loops.- The
core::rangemodule, withRangeInclusiveandRangeInclusiveIter. core::hint::cold_path, to tell the compiler a path is rarely taken.Vec::push_mutandVec::insert_mut, pluspush_front_mut,push_back_mutandinsert_mutonVecDeque, and equivalents onLinkedList, which return a mutable reference to the inserted element.From,AsRefandAsMutconversions between arrays ofMaybeUninitandMaybeUninitof arrays, and similar conversions forCell.Layout::dangling_ptr,Layout::repeat,Layout::repeat_packedandLayout::extend_packed.
In addition, fmt::from_fn and the ControlFlow::is_break and ControlFlow::is_continue methods are now usable in const contexts.
My take
Rust 1.95 is a good example of how the language evolves: absorbing patterns the community has already validated in crates, like cfg-if, and closing ergonomic gaps, like if let guards. Neither change is revolutionary, but both remove ceremonial code everyone writes.
The push_mut methods look small, but they solve an old annoyance: inserting an element and immediately needing a reference to it. Removing JSON target specs from stable is the only change that might cause friction, and even then for a narrow audience that, in practice, already depended on nightly. A smooth upgrade, and a recommended one.