News

Rust 1.96.0: New Copy Range Types, assert_matches!, and Stricter Wasm Linking

Rust 1.96.0 introduces long-awaited Copy range types, assert_matches! macros, and tightens WebAssembly symbol handling. Cargo also fixes two CVEs for third-party registries.

July 5, 2026· 2 min read
Rust 1.96.0: New Copy Range Types, assert_matches!, and Stricter Wasm Linking

Rust 1.96.0 is out, and it brings a handful of changes that working engineers will actually care about. The headline: new core::range types that are Copy, assert_matches! macros for better pattern-match diagnostics, and a breaking change to WebAssembly linking that catches undefined symbols earlier.

Copy Range Types Finally Land

The old Range types implement Iterator directly, which means they can't also be Copy — a long-standing footgun. RFC 3550 proposed a clean split: new core::range::Range, RangeFrom, and RangeInclusive implement IntoIterator instead, so they can be Copy. This lets you store slice accessors in a Copy struct without splitting start and end fields. The new RangeInclusive also exposes its fields publicly, unlike the legacy version that hid exhausted iterator state. Syntax like 0..1 still produces legacy types for now, but a future edition will switch to the new ones. If you're writing a library, prefer impl RangeBounds in public APIs, and use the new concrete types where possible.

assert_matches! and debug_assert_matches!

These macros are essentially sugar over assert!(matches!(..)), but they print the actual value on failure — a big improvement for debugging. They're not in the prelude to avoid collisions with popular third-party crates, so you'll need to import them explicitly: use core::assert_matches;. Worth adopting immediately.

WebAssembly Targets: No More --allow-undefined by Default

Starting with 1.96.0, WebAssembly targets no longer pass --allow-undefined to the linker. Undefined symbols now produce a linker error instead of silently becoming imports from the "env" module. This catches build misconfigurations and accidental symbol name collisions early. If you actually need the old behavior, you can re-enable it with RUSTFLAGS=-Clink-arg=--allow-undefined or by annotating the symbol block with #[link(wasm_import_module = "env")]. This change was announced earlier and now takes effect.

Cargo Fixes Two CVEs

Two medium/low severity vulnerabilities were fixed: CVE-2026-5223 (symlink extraction in tarballs) and CVE-2026-5222 (authentication with normalized URLs). Both only affect users of third-party registries; crates.io users are safe.

Stabilized APIs

  • assert_matches! and debug_assert_matches!
  • From<T> for AssertUnwindSafe<T>
  • From<T> for LazyCell<T, F> and LazyLock<T, F>
  • New core::range::Range, RangeFrom, RangeInclusive, and their iterators

Full details in the release notes.