Rust 1.95 in Practice: if let Guards and cfg_select! Make Match Ergonomics Real
Rust 1.95 ships two features worth actually using
Rust 1.95, released April 16, 2026, is one of those releases where the headline features show up in real code quickly. Two in particular — if let guards in match expressions and the new cfg_select! macro — solve problems you’ve probably worked around before.
if let guards in match
Before 1.95, guard clauses in match arms accepted only a plain boolean expression after if. If you wanted to destructure a value inside the guard, you had to nest a second match or extract an intermediate variable. The result was either verbose or hard to read.
Now you can write this:
match event {
Message::Data(payload) if let Some(id) = payload.user_id => {
process(id, payload)
}
_ => {}
}
The if let guard destructures right there in the arm condition. If the pattern doesn’t match, the arm is skipped — same behavior as any other guard. No nested match, no intermediate binding.
This extends the let chain stabilization from Rust 1.88, which let you chain let patterns and boolean conditions with && in if and while expressions. Match guards were the logical next step, though the RFC discussion ran for some time because of questions around variable binding scope and exhaustiveness. The final design makes new bindings introduced inside an if let guard available only to that arm’s body — not to sibling arms, and not in other guard expressions.
Where this pays off most: anywhere you match on an enum variant that carries optional or nested data you want to inspect without collapsing into a second block. Error handling with context fields, protocol message dispatch, state machine transitions. It doesn’t expand what you can express; it removes a layer of structural noise that was always there.
One thing to watch
Guards — including if let guards — are invisible to the exhaustiveness checker. The compiler still requires your match arms to cover every case without considering whether any guard might fail. So you can’t use an if let guard to silently “handle” a variant. If the guard fails, execution falls through, and you need a catch-all arm or the compiler complains. That’s correct behavior, but it trips people up the first time they try to replace a nested match with a guard and find the wildcard pattern is still required.
cfg_select!
The cfg_select! macro acts like a compile-time match on configuration flags. It fills the same role the cfg-if crate has handled for years, now built into the standard library instead of a separate dependency.
cfg_select! {
[target_os = "linux"] => {
fn platform_name() -> &'static str { "linux" }
}
[target_os = "macos"] => {
fn platform_name() -> &'static str { "macos" }
}
[_] => {
fn platform_name() -> &'static str { "other" }
}
}
The [_] arm is the catch-all. Unlike stacked #[cfg(...)] attributes on separate function definitions, cfg_select! keeps everything in one block and makes it visually clear that exactly one branch compiles per target. The wildcard is optional — omit it if you only want the code to compile on specific platforms.
For most codebases, the practical difference from cfg-if is small. The strongest case for switching is removing the dependency entirely. Library authors feel that most — one fewer transitive dependency for downstream users adds up. Existing code that already uses cfg-if doesn’t need to migrate. Both coexist fine.
The rest of 1.95
The release also stabilized several smaller library APIs, improved str::contains performance on aarch64 targets with the NEON feature, and removed stable support for custom JSON target specs. That last item matters if you maintain custom embedded targets — worth checking the full release notes before upgrading on those projects.
On the tooling side, RustRover 2026.2 added route-handler navigation for axum projects, which is useful if you’re building web backends and want to jump between a route definition and its handler. The Rust project currently has 41 active goals for 2026, with ongoing work on field projections, pin ergonomics, and an expanded Rust Reference — all of which land incrementally through the rest of the year.
