Skip to content

Commit d46ea89

Browse files
authored
Create Rust-1.96.0.md
1 parent fa78f85 commit d46ea89

1 file changed

Lines changed: 116 additions & 0 deletions

File tree

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
+++
2+
path = "2026/05/28/Rust-1.96.0"
3+
title = "Announcing Rust 1.96.0"
4+
authors = ["The Rust Release Team"]
5+
aliases = ["releases/1.96.0"]
6+
7+
[extra]
8+
release = true
9+
+++
10+
11+
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.
12+
13+
If you have a previous version of Rust installed via `rustup`, you can get 1.96.0 with:
14+
15+
```console
16+
$ rustup update stable
17+
```
18+
19+
If you don't have it already, you can [get `rustup`](https://www.rust-lang.org/install.html) from the appropriate page on our website, and check out the [detailed release notes for 1.96.0](https://doc.rust-lang.org/stable/releases.html#version-1960-2026-05-28).
20+
21+
If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (`rustup default beta`) or the nightly channel (`rustup default nightly`). Please [report](https://github.com/rust-lang/rust/issues/new/choose) any bugs you might come across!
22+
23+
## What's in 1.96.0 stable
24+
25+
### New `Range*` types
26+
27+
Many users expect `Range` and related `core::ops` types to be `Copy`, but this is not the case: they implement `Iterator` directly, and [it is a footgun to implement both `Iterator` and `Copy` on the same type](https://rust-lang.github.io/rust-clippy/rust-1.95.0/index.html#copy_iterator) so this has been avoided. [RFC3550] proposed a set of replacement range types that implement `IntoIterator` rather than `Iterator`, meaning they can also be `Copy`. The standard library portion of that RFC is now stable, introducing:
28+
29+
- `core::range::Range`
30+
- `core::range::RangeFrom`
31+
- `core::range::RangeInclusive`
32+
- Associated iterators
33+
34+
A Rust version in the near future will also add `core::range::RangeFull` and `core::range::RangeTo` as re-exports from `core::ops` (these do not implement `Iterator` and already implement `Copy`), and `core::range::legacy::*` as the new home for the current ranges. Range syntax like `0..1` still produces the legacy types for now, but will be updated to `core::range` types in a future edition.
35+
36+
With these stabilizations, it is now possible to store slice accessors in `Copy` types without splitting `start` and `end`:
37+
38+
```rust
39+
use core::range::Range;
40+
41+
#[derive(Clone, Copy)]
42+
pub struct Span(Range<usize>);
43+
44+
impl Span {
45+
pub fn of(self, s: &str) -> &str {
46+
&s[self.0]
47+
}
48+
}
49+
```
50+
51+
The new `RangeInclusive` also makes its fields public, unlike the legacy version which avoided exposing the exhausted iterator state. This isn't a concern with the new type since it must be converted to begin iteration.
52+
53+
Library authors should consider making use of `impl RangeBounds` in public API, which accepts both legacy and new range types. If a concrete type is needed, prefer using new ranges as this will eventually become the default.
54+
55+
[RFC3550]: https://rust-lang.github.io/rfcs/3550-new-range.html
56+
57+
### Assert matching patterns
58+
59+
The new macros `assert_matches!` and `debug_assert_matches!` check that a value matches a given pattern, panicking with a `Debug` representation of the value otherwise. These are essentially the same as `assert!(matches!(..))` and `debug_assert!(matches!(..))`, but the printed value improves the possibility of diagnosing the failure.
60+
61+
These new macros have not been added to the standard prelude, because they would collide with popular third-party crates that provide macros with the same name. Instead, they should be manually imported from `core` or `std` before use.
62+
63+
```rust
64+
use core::assert_matches;
65+
66+
/// [Random Number](https://xkcd.com/221/)
67+
fn get_random_number() -> u32 {
68+
// chosen by a fair dice roll.
69+
// guaranteed to be random.
70+
4
71+
}
72+
73+
fn main() {
74+
assert_matches!(get_random_number(), 1..=6);
75+
}
76+
```
77+
78+
### Changes to WebAssembly targets
79+
80+
WebAssembly targets no longer pass `--allow-undefined` to the linker which means that undefined symbols when linking are now a linker error instead of being converted to WebAssembly imports from the `"env"` module. This change prevents modules from linking unless all linking-related symbols are defined to catch bugs earlier and prevent accidental issues with symbol naming or similar.
81+
82+
Undefined linking-related symbols are often indicative of build-time related bugs or misconfiguration. If, however, the old behavior is intended then it can be re-enabled with `RUSTFLAGS=-Clink-arg=--allow-undefined` or by editing the source code and using `#[link(wasm_import_module = "env")]` on the block defining the symbol.
83+
84+
This change was [previously announced](https://blog.rust-lang.org/2026/04/04/changes-to-webassembly-targets-and-handling-undefined-symbols/) on this blog, and now takes effect in Rust 1.96.
85+
86+
### Stabilized APIs
87+
88+
- [`assert_matches!`](https://doc.rust-lang.org/stable/std/macro.assert_matches.html)
89+
- [`debug_assert_matches!`](https://doc.rust-lang.org/stable/std/macro.debug_assert_matches.html)
90+
- [`From<T> for AssertUnwindSafe<T>`](https://doc.rust-lang.org/stable/std/panic/struct.AssertUnwindSafe.html#impl-From%3CT%3E-for-AssertUnwindSafe%3CT%3E)
91+
- [`From<T> for LazyCell<T, F>`](https://doc.rust-lang.org/stable/std/cell/struct.LazyCell.html#impl-From%3CT%3E-for-LazyCell%3CT,+F%3E)
92+
- [`From<T> for LazyLock<T, F>`](https://doc.rust-lang.org/stable/std/sync/struct.LazyLock.html#impl-From%3CT%3E-for-LazyLock%3CT,+F%3E)
93+
- [`core::range::RangeToInclusive`](https://doc.rust-lang.org/stable/core/range/struct.RangeToInclusive.html)
94+
- [`core::range::RangeToInclusiveIter`](https://doc.rust-lang.org/stable/core/range/struct.RangeToInclusiveIter.html)
95+
- [`core::range::RangeFrom`](https://doc.rust-lang.org/stable/core/ops/struct.RangeFrom.html)
96+
- [`core::range::RangeFromIter`](https://doc.rust-lang.org/stable/core/ops/struct.RangeFromIter.html)
97+
- [`core::range::Range`](https://doc.rust-lang.org/stable/std/range/struct.Range.html)
98+
- [`core::range::RangeIter`](https://doc.rust-lang.org/stable/std/range/struct.RangeIter.html)
99+
100+
### Two Cargo advisories
101+
102+
Rust 1.96 contains fixes for two vulnerabilities for users of third-party registries.
103+
104+
- [CVE-2026-5223](https://blog.rust-lang.org/2026/05/25/cve-2026-5223/) is a **medium** severity vulnerability regarding extraction of crate tarballs with symlinks.
105+
106+
- [CVE-2026-5222](https://blog.rust-lang.org/2026/05/25/cve-2026-5222/) is a **low** severity vulnerability regarding authentication with normalized URLs.
107+
108+
Users of crates.io are **not affected** by either vulnerability.
109+
110+
### Other changes
111+
112+
Check out everything that changed in [Rust](https://github.com/rust-lang/rust/releases/tag/1.96.0), [Cargo](https://doc.rust-lang.org/nightly/cargo/CHANGELOG.html#cargo-196-2026-05-28), and [Clippy](https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-196).
113+
114+
## Contributors to 1.96.0
115+
116+
Many people came together to create Rust 1.96.0. We couldn't have done it without all of you. [Thanks!](https://thanks.rust-lang.org/rust/1.96.0/)

0 commit comments

Comments
 (0)