Announcing Rust 1.96.0
Source: Rust Blog
Rust 1.96.0 – Release Announcement
The Rust team is happy to announce a new version of Rust, 1.96.0.
Rust is a programming language empowering everyone to build reliable and efficient software.
Installation
If you already have a Rust toolchain installed via rustup, upgrade to the latest stable release:
$ rustup update stable
If you don’t have rustup yet, you can get it here.
For a full list of changes, see the detailed release notes for 1.96.0.
Trying future releases
Want to help test upcoming releases? Switch to the beta or nightly channel:
$ rustup default beta # use the beta channel
$ rustup default nightly # use the nightly channel
If you encounter any bugs, please report them!
What’s new in 1.96.0 (stable)
New Range* types
Historically, Range and related core::ops types are not Copy because they implement Iterator directly. Implementing both Iterator and Copy is a foot‑gun (see the Clippy lint).
RFC 3550 introduced a set of replacement range types that implement IntoIterator instead, allowing them to be Copy. The standard‑library portion of that RFC is now stable, adding the following types:
core::range::Rangecore::range::RangeFromcore::range::RangeInclusive- Associated iterator types
A future Rust version will also add:
core::range::RangeFullcore::range::RangeTo(re‑exports fromcore::ops; both areCopy)core::range::legacy::*(the new home for the current legacy ranges)
Note: The syntax
0..1still produces the legacy types for now; it will be updated to the newcore::rangetypes in a later edition.
Example: storing slice accessors in a Copy type
use core::range::Range;
#[derive(Clone, Copy)]
pub struct Span(Range);
impl Span {
pub fn of(self, s: &str) -> &str {
&s[self.0]
}
}
RangeInclusive now makes its fields public, unlike the legacy version, because the new type must be converted to an iterator before use.
API tip: Prefer impl RangeBounds in public signatures; it accepts both legacy and new range types. When a concrete type is required, use the new ranges—they will become the default eventually.
Assert‑matching macros
Two new macros, assert_matches! and debug_assert_matches!, verify that a value matches a pattern and panic (or debug‑panic) with a Debug representation of the value when it does not.
They are equivalent to assert!(matches!(…)) and debug_assert!(matches!(…)), but the printed value makes diagnosing failures easier.
These macros are not in the prelude to avoid colliding with third‑party crates that provide macros of the same name. Import them manually:
use core::assert_matches;
/// [Random Number](https://xkcd.com/221/)
fn get_random_number() -> u32 {
// chosen by a fair dice roll.
// guaranteed to be random.
4
}
fn main() {
assert_matches!(get_random_number(), 1..=6);
}
Changes to WebAssembly targets
WebAssembly targets no longer pass --allow-undefined to the linker. Consequently, undefined symbols now cause a linker error instead of being silently turned into imports from the "env" module. This catches bugs earlier and prevents accidental symbol‑naming issues.
If you need the old behaviour, you can re‑enable it:
RUSTFLAGS="-Clink-arg=--allow-undefined"
or by adding #[link(wasm_import_module = "env")] to the relevant block.
The change was previously announced and takes effect in Rust 1.96.
Stabilized APIs
assert_matches!debug_assert_matches!From for AssertUnwindSafe–From for LazyCell–From for LazyLock–
Range types and iterators
core::range::RangeToInclusivecore::range::RangeToInclusiveItercore::range::RangeFromcore::range::RangeFromItercore::range::Rangecore::range::RangeIter
Security advisories
Rust 1.96 contains fixes for two vulnerabilities affecting users of third‑party registries.
| CVE | Severity | Description |
|---|---|---|
| CVE‑2026‑5223 | Medium | Issue with extraction of crate tarballs. Details: |
| CVE‑2026‑5271 | High | (Add description and link when available) |
Upgrade to Rust 1.96.0 to obtain the patches.
Enjoy the new release! 🚀
Security fixes
- CVE‑2026‑5221 – A low severity vulnerability involving symlink handling.
- CVE‑2026‑5222 – A low severity vulnerability concerning authentication with normalized URLs.
Note: Users of crates.io are not affected by either vulnerability.
Other changes
Explore everything that changed in the latest releases:
Contributors to 1.96.0
Many people came together to create Rust 1.96.0. We couldn’t have done it without all of you.
Thanks!