Rust Release Notes
32 release notes curated from 23 sources by the Releasebot Team. Last updated: May 29, 2026
- May 28, 2026
- Date parsed from source:May 28, 2026
- First seen by Releasebot:May 29, 2026
Announcing Rust 1.96.0
Rust releases 1.96.0 with stable new range types, helpful assert_matches macros, and a WebAssembly linking change that catches undefined symbols earlier. It also includes Cargo security fixes for third-party registries and other stabilization updates.
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.
If you have a previous version of Rust installed via rustup, you can get 1.96.0 with:
$ rustup update stableIf you don't have it already, you can get rustup from the appropriate page on our website, and check out the detailed release notes for 1.96.0.
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 any bugs you might come across!
What's in 1.96.0 stable
New Range* types
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 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:
- core::range::Range
- core::range::RangeFrom
- core::range::RangeInclusive
- Associated iterators
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.
With these stabilizations, it is now possible to store slice accessors in Copy types without splitting start and end:
use core::range::Range; # [derive(Clone, Copy)] pub struct Span(Range<usize>); impl Span { pub fn of(self, s: &str) -> &str { &s[self.0] } }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.
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.
Assert matching patterns
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.
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.
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 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.
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.
This change was previously announced on this blog, and now takes effect in Rust 1.96.
Stabilized APIs
- assert_matches!
- debug_assert_matches!
- From for AssertUnwindSafe
- From for LazyCell<T, F>
- From for LazyLock<T, F>
- core::range::RangeToInclusive
- core::range::RangeToInclusiveIter
- core::range::RangeFrom
- core::range::RangeFromIter
- core::range::Range
- core::range::RangeIter
Two Cargo advisories
Rust 1.96 contains fixes for two vulnerabilities for users of third-party registries.
- CVE-2026-5223 is a medium severity vulnerability regarding extraction of crate tarballs with symlinks.
- CVE-2026-5222 is a low severity vulnerability regarding authentication with normalized URLs.
Users of crates.io are not affected by either vulnerability.
Other changes
Check out everything that changed in Rust, Cargo, and Clippy.
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!
Original source - May 28, 2026
- Date parsed from source:May 28, 2026
- First seen by Releasebot:May 29, 2026
Rust 1.96.0
Rust ships a broad release with compiler, Cargo, rustdoc, and library improvements, including new stabilized APIs, better target and assembly support, dependency publishing flexibility, security fixes, and several compatibility and diagnostics updates.
Language
- Allow passing expr metavariable to cfg
- Always coerce never types in tuple expressions
- Avoid incorrect inference guidance of function arguments in rare cases
- Support s390x vector registers in inline assembly
- Allow using constants of type ManuallyDrop as patterns (fixing a regression introduced in 1.94.0)
Compiler
- Enable link relaxation feature for LoongArch Linux targets
- Update riscv64gc-unknown-fuchsia baseline to RVA22 + vector
Libraries
- Support iterating over ranges of NonZero integers
- refactor 'valid for read/write' definition: exclude null; add that as an exception on individual methods instead
- Fix SGX delayed host lookup via ToSocketAddr
Stabilized APIs
- assert_matches!
- debug_assert_matches!
- From<T> for AssertUnwindSafe<T>
- From<T> for LazyCell<T, F>
- From<T> for LazyLock<T, F>
- core::range::RangeToInclusive
- core::range::RangeToInclusiveIter
- core::range::RangeFrom
- core::range::RangeFromIter
- core::range::Range
- core::range::RangeIter
Cargo
- Allow a dependency to specify both a git repository and an alternate registry. Just like with crates.io, the git repository will be used locally, but the registry version will be used when published.
- Added target.'cfg(..)'.rustdocflags support in configuration.
- Fixed CVE-2026-5222 and CVE-2026-5223.
Rustdoc
- Deprecation notes are now rendered like any other documentation. Previously they used the css white-space: pre-wrap; property and stripped any <p> elements from the rendered html, however this caused issues and unintuitive behavior. The new behavior should be more predictable, however some multi-line deprecation notes will now be rendered as as single lines. If this is undesirable, you can use the standard markdown method of forcing a linebreak, which is two spaces followed by a newline ("\n").
- Don't emit rustdoc missing_doc_code_examples lint on impl items
- Seperate methods and associated functions in sidebar
Compatibility Notes
- Fix layout of #[repr(Int)] enums in some edge cases involving fields of uninhabited zero-sized types
- Prevent unsize-coercing into Pin<Foo> where Foo doesn't implement Deref. Some such coercions were previously allowed, but produce a type with no useful public API.
- rustc: Stop passing --allow-undefined on wasm targets
- Gate the accidentally stabilized #![reexport_test_harness_main] attribute
- Error on return-position-impl-trait-in-traits whose types are too private
- Report the uninhabited_static lint in dependencies and make it deny-by-default
- Distributed builds now contain non-split debuginfo for windows-gnu This appears to improve the quality of backtraces. This change has no effect on the defaults for the output of rustc/cargo on these targets.
- Check const generic arguments are correctly typed in more positions
- Remove -Csoft-float
- Importing structs with ::{self [as name]}, e.g., struct S {}; use S::{self as Other};, is now no longer permitted because {self} imports require a module parent.
- For export_name, link_name, and link_section attributes, if multiple of the same attribute is present, the first one now takes precedence.
- Update the minimum external LLVM to 21
- On avr targets, C's double type is 32-bit by default, so change c_double to f32 on avr targets to match. This is a breaking change, but necessary to make c_double match C's double.
Internal Changes
These changes do not affect any public interfaces of Rust, but they represent significant improvements to the performance or internals of rustc and related tools.
- JSON targets: aarch64 softfloat targets now have to have rustc_abi set to "softfloat"
- target specs: stricter checks for LLVM ABI values, and correlate that with cfg(target_abi)
All of your release notes in one feed
Join Releasebot and get updates from Rust and hundreds of other software products.
- Apr 16, 2026
- Date parsed from source:Apr 16, 2026
- First seen by Releasebot:May 23, 2026
Announcing Rust 1.95.0
Rust releases 1.95.0 with new cfg_select! macro, if-let guards in match expressions, and a broad set of stabilized APIs. It also expands const-context support and removes stable support for custom JSON target specs.
The Rust team is happy to announce a new version of Rust, 1.95.0. Rust is a programming language empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via rustup, you can get 1.95.0 with:
$ rustup update stableIf you don't have it already, you can get rustup from the appropriate page on our website, and check out the detailed release notes for 1.95.0.
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 any bugs you might come across!
What's in 1.95.0 stable
cfg_select!
Rust 1.95 introduces a cfg_select! macro that acts roughly similar to a compile-time match on cfgs. This fulfills the same purpose as the popular cfg-if crate, although with a different syntax. cfg_select! expands to the right-hand side of the first arm whose configuration predicate evaluates to true. Some examples:
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", };if-let guards in matches
Rust 1.88 stabilized let chains. Rust 1.95 brings that capability into match expressions, allowing for conditionals based on pattern matching.
match value { Some(x) if let Ok(y) = compute(x) => { // Both `x` and `y` are available here println!("{},{}", x, y); } _ => {} }Note that the compiler will not currently consider the patterns matched in if let guards as part of the exhaustiveness evaluation of the overall match, just like if guards.
Stabilized APIs
- MaybeUninit<[T; N]>: From<[MaybeUninit; N]>
- MaybeUninit<[T; N]>: AsRef<[MaybeUninit; N]>
- MaybeUninit<[T; N]>: AsRef<[MaybeUninit]>
- MaybeUninit<[T; N]>: AsMut<[MaybeUninit; N]>
- MaybeUninit<[T; N]>: AsMut<[MaybeUninit]>
- [MaybeUninit; N]: From<MaybeUninit<[T; N]>>
- Cell<[T; N]>: AsRef<[Cell; N]>
- Cell<[T; N]>: AsRef<[Cell]>
- Cell<[T]>: AsRef<[Cell]>
- bool: TryFrom<{integer}>
- AtomicPtr::update
- AtomicPtr::try_update
- AtomicBool::update
- AtomicBool::try_update
- AtomicIn::update
- AtomicIn::try_update
- AtomicUn::update
- AtomicUn::try_update
- cfg_select!
- mod core::range
- core::range::RangeInclusive
- core::range::RangeInclusiveIter
- core::hint::cold_path
- <*const T>::as_ref_unchecked
- <*mut T>::as_ref_unchecked
- <*mut T>::as_mut_unchecked
- Vec::push_mut
- Vec::insert_mut
- VecDeque::push_front_mut
- VecDeque::push_back_mut
- VecDeque::insert_mut
- LinkedList::push_front_mut
- LinkedList::push_back_mut
- Layout::dangling_ptr
- Layout::repeat
- Layout::repeat_packed
- Layout::extend_packed
These previously stable APIs are now stable in const contexts:
- fmt::from_fn
- ControlFlow::is_break
- ControlFlow::is_continue
Destabilized JSON target specs
Rust 1.95 removes support on stable for passing a custom target specification to rustc. This should not affect any Rust users using a fully stable toolchain, as building the standard library (including just core) already required using nightly-only features.
We're also gathering use cases for custom targets on the tracking issue as we consider whether some form of this feature should eventually be stabilized.
Other changes
Check out everything that changed in Rust, Cargo, and Clippy.
Contributors to 1.95.0
Many people came together to create Rust 1.95.0. We couldn't have done it without all of you. Thanks!
Original source - Mar 26, 2026
- Date parsed from source:Mar 26, 2026
- First seen by Releasebot:May 23, 2026
Announcing Rust 1.94.1
Rust releases 1.94.1, a point update that fixes three regressions from 1.94.0 and includes a Cargo security update to address CVE-2026-33055 and CVE-2026-33056. It also improves stability for thread spawning, OpenOptionsExt, Clippy, and FreeBSD users.
The Rust team has published a new point release of Rust, 1.94.1. Rust is a programming language that is empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via rustup, getting Rust 1.94.1 is as easy as:
rustup update stableIf you don't have it already, you can get rustup from the appropriate page on our website.
What's in 1.94.1
Rust 1.94.1 resolves three regressions that were introduced in the 1.94.0 release.
- Fix std::thread::spawn on wasm32-wasip1-threads
- Remove new methods added to std::os::windows::fs::OpenOptionsExt The new methods were unstable, but the trait itself is not sealed and so cannot be extended with non-default methods.
- Clippy: fix ICE in match_same_arms
- Cargo: downgrade curl-sys to 0.4.83 This fixes certificate validation error for some users on some versions of FreeBSD. See this issue for more details.
And a security fix:
- Cargo: Update tar to 0.4.45 This resolves CVE-2026-33055 and CVE-2026-33056. Users of crates.io are not affected. See blog for more details.
Contributors to 1.94.1
Many people came together to create Rust 1.94.1. We couldn't have done it without all of you. Thanks!
Original source - Mar 5, 2026
- Date parsed from source:Mar 5, 2026
- First seen by Releasebot:May 23, 2026
Announcing Rust 1.94.0
Rust releases 1.94.0 with new array_windows support for slices, Cargo config includes and TOML 1.1 parsing, plus a set of stabilized APIs and const-context improvements for a smoother development experience.
The Rust team is happy to announce a new version of Rust, 1.94.0. Rust is a programming language empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via rustup, you can get 1.94.0 with:
$ rustup update stableIf you don't have it already, you can get rustup from the appropriate page on our website, and check out the detailed release notes for 1.94.0.
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 any bugs you might come across!
What's in 1.94.0 stable
Array windows
Rust 1.94 adds array_windows, an iterating method for slices. It works just like windows but with a constant length, so the iterator items are &[T; N] rather than dynamically-sized &[T]. In many cases, the window length may even be inferred by how the iterator is used!
For example, part of one 2016 Advent of Code puzzle is looking for ABBA patterns: "two different characters followed by the reverse of that pair, such as xyyx or abba." If we assume only ASCII characters, that could be written by sweeping windows of the byte slice like this:
fn has_abba(s: &str) -> bool { s.as_bytes().array_windows().any(|[a1, b1, b2, a2]| (a1 != b1) && (a1 == a2) && (b1 == b2)) }The destructuring argument pattern in that closure lets the compiler infer that we want windows of 4 here. If we had used the older .windows(4) iterator, then that argument would be a slice which we would have to index manually, hoping that runtime bounds-checking will be optimized away.
Cargo config inclusion
Cargo now supports the include key in configuration files (.cargo/config.toml), enabling better organization, sharing, and management of Cargo configurations across projects and environments. These include paths may also be marked optional if they might not be present in some circumstances, e.g. depending on local developer choices.
# array of paths include = [ "frodo.toml", "samwise.toml", ] # inline tables for more control include = [ { path = "required.toml" }, { path = "optional.toml", optional = true }, ]See the full include documentation for more details.
TOML 1.1 support in Cargo
Cargo now parses TOML v1.1 for manifests and configuration files. See the TOML release notes for detailed changes, including:
- Inline tables across multiple lines and with trailing commas
- \xHH and \e string escape characters
- Optional seconds in times (sets to 0)
For example, a dependency like this:
serde = { version = "1.0", features = ["derive"] }... can now be written like this:
serde = { version = "1.0", features = ["derive"], }Note that using these features in Cargo.toml will raise your development MSRV (minimum supported Rust version) to require this new Cargo parser, and third-party tools that read the manifest may also need to update their parsers. However, Cargo automatically rewrites manifests on publish to remain compatible with older parsers, so it is still possible to support an earlier MSRV for your crate's users.
Stabilized APIs
- <[T]>::array_windows
- <[T]>::element_offset
- LazyCell::get
- LazyCell::get_mut
- LazyCell::force_mut
- LazyLock::get
- LazyLock::get_mut
- LazyLock::force_mut
- impl TryFrom for usize
- std::iter::Peekable::next_if_map
- std::iter::Peekable::next_if_map_mut
- x86 avx512fp16 intrinsics (excluding those that depend directly on the unstable f16 type)
- AArch64 NEON fp16 intrinsics (excluding those that depend directly on the unstable f16 type)
- f32::consts::EULER_GAMMA
- f64::consts::EULER_GAMMA
- f32::consts::GOLDEN_RATIO
- f64::consts::GOLDEN_RATIO
These previously stable APIs are now stable in const contexts:
- f32::mul_add
- f64::mul_add
Other changes
Check out everything that changed in Rust, Cargo, and Clippy.
Contributors to 1.94.0
Many people came together to create Rust 1.94.0. We couldn't have done it without all of you. Thanks!
Original source - Feb 12, 2026
- Date parsed from source:Feb 12, 2026
- First seen by Releasebot:May 23, 2026
Announcing Rust 1.93.1
Rust ships 1.93.1, a point release that fixes three regressions from 1.93.0, including an internal compiler error affecting rustfmt, a clippy false positive, and wasm32-wasip2 file descriptor leaks.
The Rust team has published a new point release of Rust, 1.93.1. Rust is a programming language that is empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via rustup, getting Rust 1.93.1 is as easy as:
rustup update stableIf you don't have it already, you can get rustup from the appropriate page on our website.
What's in 1.93.1
Rust 1.93.1 resolves three regressions that were introduced in the 1.93.0 release.
- Don't try to recover a keyword as a non-keyword identifier, fixing an internal compiler error (ICE) that especially affected rustfmt.
- Fix a clippy::panicking_unwrap false-positive on field access with an implicit dereference.
- Revert an update to wasm-related dependencies, fixing file descriptor leaks on the wasm32-wasip2 target. This only affects the rustup component for this target, so downstream toolchain builds should check their own dependencies too.
Contributors to 1.93.1
Many people came together to create Rust 1.93.1. We couldn't have done it without all of you. Thanks!
Original source - Jan 22, 2026
- Date parsed from source:Jan 22, 2026
- First seen by Releasebot:May 23, 2026
Announcing Rust 1.93.0
Rust releases 1.93.0 with musl 1.2.5 updates for more reliable Linux static builds, allocator internals that better support thread-local use, finer cfg control in asm!, and a broad set of stabilized APIs.
The Rust team is happy to announce a new version of Rust, 1.93.0. Rust is a programming language empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via rustup, you can get 1.93.0 with:
$ rustup update stableIf you don't have it already, you can get rustup from the appropriate page on our website, and check out the detailed release notes for 1.93.0.
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 any bugs you might come across!
What's in 1.93.0 stable
Update bundled musl to 1.2.5
The various *-linux-musl targets now all ship with musl 1.2.5. This primarily affects static musl builds for x86_64, aarch64, and powerpc64le which bundled musl 1.2.3. This update comes with several fixes and improvements, and a breaking change that affects the Rust ecosystem.
For the Rust ecosystem, the primary motivation for this update is to receive major improvements to musl's DNS resolver which shipped in 1.2.4 and received bug fixes in 1.2.5. When using musl targets for static linking, this should make portable Linux binaries that do networking more reliable, particularly in the face of large DNS records and recursive nameservers.
However, 1.2.4 also comes with a breaking change: the removal of several legacy compatibility symbols that the Rust libc crate was using. A fix for this was shipped in libc 0.2.146 in June 2023 (2.5 years ago), and we believe has sufficiently widely propagated that we're ready to make the change in Rust targets.
See our previous announcement for more details.
Allow the global allocator to use thread-local storage
Rust 1.93 adjusts the internals of the standard library to permit global allocators written in Rust to use std's thread_local! and std::thread::current without re-entrancy concerns by using the system allocator instead.
See docs for details.
cfg attributes on asm! lines
Previously, if individual parts of a section of inline assembly needed to be cfg'd, the full asm! block would need to be repeated with and without that section. In 1.93, cfg can now be applied to individual statements within the asm! block.
Stabilized APIs
- <[MaybeUninit]>::assume_init_drop
- <[MaybeUninit]>::assume_init_ref
- <[MaybeUninit]>::assume_init_mut
- <[MaybeUninit]>::write_copy_of_slice
- <[MaybeUninit]>::write_clone_of_slice
- String::into_raw_parts
- Vec::into_raw_parts
- ::unchecked_neg
- ::unchecked_shl
- ::unchecked_shr
- ::unchecked_shl
- ::unchecked_shr
- <[T]>::as_array
- <[T]>::as_mut_array
- <*const [T]>::as_array
- <*mut [T]>::as_mut_array
- VecDeque::pop_front_if
- VecDeque::pop_back_if
- Duration::from_nanos_u128
- char::MAX_LEN_UTF8
- char::MAX_LEN_UTF16
- std::fmt::from_fn
- std::fmt::FromFn
Other changes
Check out everything that changed in Rust, Cargo, and Clippy.
Contributors to 1.93.0
Many people came together to create Rust 1.93.0. We couldn't have done it without all of you. Thanks!
Original source - Dec 11, 2025
- Date parsed from source:Dec 11, 2025
- First seen by Releasebot:May 23, 2026
Announcing Rust 1.92.0
Rust ships version 1.92.0 with tighter never type linting, smarter must-use handling, and improved backtraces on Linux when panic abort is enabled. It also validates macro_export input and stabilizes several APIs, including new zeroed allocation helpers and const-friendly slice rotation.
The Rust team is happy to announce a new version of Rust, 1.92.0. Rust is a programming language empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via rustup, you can get 1.92.0 with:
$ rustup update stableIf you don't have it already, you can get rustup from the appropriate page on our website, and check out the detailed release notes for 1.92.0.
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 any bugs you might come across!
What's in 1.92.0 stable
Deny-by-default never type lints
The language and compiler teams continue to work on stabilization of the never type. In this release the never_type_fallback_flowing_into_unsafe and dependency_on_unit_never_type_fallback future compatibility lints were made deny-by-default, meaning they will cause a compilation error when detected.
It's worth noting that while this can result in compilation errors, it is still a lint; these lints can all be #[allow]ed. These lints also will only fire when building the affected crates directly, not when they are built as dependencies (though a warning will be reported by Cargo in such cases).
These lints detect code which is likely to be broken by the never type stabilization. It is highly advised to fix them if they are reported in your crate graph.
We believe there to be approximately 500 crates affected by this lint. Despite that, we believe this to be acceptable, as lints are not a breaking change and it will allow for stabilizing the never type in the future. For more in-depth justification, see the Language Team's assessment.
unused_must_use no longer warns about Result<(), UninhabitedType>
Rust's unused_must_use lint warns when ignoring the return value of a function, if the function or its return type is annotated with #[must_use]. For instance, this warns if ignoring a return type of Result, to remind you to use ?, or something like .expect("...").
However, some functions return Result, but the error type they use is not actually "inhabited", meaning you cannot construct any values of that type (e.g. the ! or Infallible types).
The unused_must_use lint now no longer warns on Result<(), UninhabitedType>, or on ControlFlow<UninhabitedType, ()>. For instance, it will not warn on Result<(), Infallible>. This avoids having to check for an error that can never happen.
This is particularly useful with the common pattern of a trait with an associated error type, where the error type may sometimes be infallible:
trait UsesAssocErrorType { type Error; fn method(&self) -> Result<(), Self::Error>; } struct CannotFail; impl UsesAssocErrorType for CannotFail { type Error = core::convert::Infallible; fn method(&self) -> Result<(), Self::Error> { Ok(()) } } struct CanFail; impl UsesAssocErrorType for CanFail { type Error = std::io::Error; fn method(&self) -> Result<(), Self::Error> { Err(std::io::Error::other("something went wrong")) } } fn main() { CannotFail.method(); // No warning CanFail.method(); // Warning: unused `Result` that must be used }Emit unwind tables even when -Cpanic=abort is enabled on linux
Backtraces with -Cpanic=abort previously worked in Rust 1.22 but were broken in Rust 1.23, as we stopped emitting unwind tables with -Cpanic=abort. In Rust 1.45 a workaround in the form of -Cforce-unwind-tables=yes was stabilized.
In Rust 1.92 unwind tables will be emitted by default even when -Cpanic=abort is specified, allowing for backtraces to work properly. If unwind tables are not desired then users should use -Cforce-unwind-tables=no to explicitly disable them being emitted.
Validate input to #[macro_export]
Over the past few releases, many changes were made to the way built-in attributes are processed in the compiler. This should greatly improve the error messages and warnings Rust gives for built-in attributes and especially make these diagnostics more consistent among all of the over 100 built-in attributes.
To give a small example, in this release specifically, Rust became stricter in checking what arguments are allowed to macro_export by upgrading that check to a "deny-by-default lint" that will be reported in dependencies.
Stabilized APIs
- NonZero<u{N}>::div_ceil
- Location::file_as_c_str
- RwLockWriteGuard::downgrade
- Box::new_zeroed
- Box::new_zeroed_slice
- Rc::new_zeroed
- Rc::new_zeroed_slice
- Arc::new_zeroed
- Arc::new_zeroed_slice
- btree_map::Entry::insert_entry
- btree_map::VacantEntry::insert_entry
- impl Extend<proc_macro::Group> for proc_macro::TokenStream
- impl Extend<proc_macro::Literal> for proc_macro::TokenStream
- impl Extend<proc_macro::Punct> for proc_macro::TokenStream
- impl Extend<proc_macro::Ident> for proc_macro::TokenStream
These previously stable APIs are now stable in const contexts:
- <[_]>::rotate_left
- <[_]>::rotate_right
Other changes
Check out everything that changed in Rust, Cargo, and Clippy.
Contributors to 1.92.0
Many people came together to create Rust 1.92.0. We couldn't have done it without all of you. Thanks!
Original source - Nov 10, 2025
- Date parsed from source:Nov 10, 2025
- First seen by Releasebot:May 23, 2026
Announcing Rust 1.91.1
Rust releases 1.91.1, a point update that fixes two regressions from 1.91.0, including Wasm linker and runtime errors and Cargo target directory locking on illumos. It restores stability across builds and runtimes.
The Rust team has published a new point release of Rust, 1.91.1. Rust is a programming language that is empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via rustup, getting Rust 1.91.1 is as easy as:
rustup update stableIf you don't have it already, you can get rustup from the appropriate page on our website.
What's in 1.91.1
Rust 1.91.1 includes fixes for two regressions introduced in the 1.91.0 release.
Linker and runtime errors on Wasm
Most targets supported by Rust identify symbols by their name, but Wasm identifies them with a symbol name and a Wasm module name. The #[link(wasm_import_module)] attribute allows to customize the Wasm module name an extern block refers to:
# [link(wasm_import_module = "hello")] extern "C" { pub fn world(); }Rust 1.91.0 introduced a regression in the attribute, which could cause linker failures during compilation ("import module mismatch" errors) or the wrong function being used at runtime (leading to undefined behavior, including crashes and silent data corruption). This happened when the same symbol name was imported from two different Wasm modules across multiple Rust crates.
Rust 1.91.1 fixes the regression. More details are available in issue #148347.
Cargo target directory locking broken on illumos
Cargo relies on locking the target/ directory during a build to prevent concurrent invocations of Cargo from interfering with each other. Not all filesystems support locking (most notably some networked ones): if the OS returns the Unsupported error when attempting to lock, Cargo assumes locking is not supported and proceeds without it.
Cargo 1.91.0 switched from custom code interacting with the OS APIs to the File::lock standard library method (recently stabilized in Rust 1.89.0). Due to an oversight, that method always returned Unsupported on the illumos target, causing Cargo to never lock the build directory on illumos regardless of whether the filesystem supported it.
Rust 1.91.1 fixes the oversight in the standard library by enabling the File::lock family of functions on illumos, indirectly fixing the Cargo regression.
Contributors to 1.91.1
Many people came together to create Rust 1.91.1. We couldn't have done it without all of you. Thanks!
Original source - Oct 30, 2025
- Date parsed from source:Oct 30, 2025
- First seen by Releasebot:May 23, 2026
Announcing Rust 1.91.0
Rust releases 1.91.0 with a major Windows platform boost, promoting aarch64-pc-windows-msvc to Tier 1 support. It also adds a warn-by-default lint for dangling raw pointers from locals and stabilizes a broad set of APIs and const-context capabilities.
The Rust team is happy to announce a new version of Rust, 1.91.0. Rust is a programming language empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via rustup, you can get 1.91.0 with:
$ rustup update stableIf you don't have it already, you can get rustup from the appropriate page on our website, and check out the detailed release notes for 1.91.0.
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 any bugs you might come across!What's in 1.91.0 stable
aarch64-pc-windows-msvc is now a Tier 1 platform
The Rust compiler supports a wide variety of targets, but the Rust Team can't provide the same level of support for all of them. To clearly mark how supported each target is, we use a tiering system:
- Tier 3 targets are technically supported by the compiler, but we don't check whether their code build or passes the tests, and we don't provide any prebuilt binaries as part of our releases.
- Tier 2 targets are guaranteed to build and we provide prebuilt binaries, but we don't execute the test suite on those platforms: the produced binaries might not work or might have bugs.
- Tier 1 targets provide the highest support guarantee, and we run the full suite on those platforms for every change merged in the compiler. Prebuilt binaries are also available.
Rust 1.91.0 promotes the aarch64-pc-windows-msvc target to Tier 1 support, bringing our highest guarantees to users of 64-bit ARM systems running Windows.
Add lint against dangling raw pointers from local variables
While Rust's borrow checking prevents dangling references from being returned, it doesn't track raw pointers. With this release, we are adding a warn-by-default lint on raw pointers to local variables being returned from functions. For example, code like this:
fn f() -> *const u8 { let x = 0; &x }will now produce a lint:
warning: a dangling pointer will be produced because the local variable `x` will be dropped --> src/lib.rs:3:5 | 1 | fn f() -> *const u8 { | --------- return type of the function is `*const u8` 2 | let x = 0; | - `x` is part the function and will be dropped at the end of the function 3 | &x | ^^ = note: pointers do not have a lifetime; after returning, the `u8` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned = note: `#[warn(dangling_pointers_from_locals)]` on by defaultNote that the code above is not unsafe, as it itself doesn't perform any dangerous operations. Only dereferencing the raw pointer after the function returns would be unsafe. We expect future releases of Rust to add more functionality helping authors to safely interact with raw pointers, and with unsafe code more generally.
Stabilized APIs
- Path::file_prefix
- AtomicPtr::fetch_ptr_add
- AtomicPtr::fetch_ptr_sub
- AtomicPtr::fetch_byte_add
- AtomicPtr::fetch_byte_sub
- AtomicPtr::fetch_or
- AtomicPtr::fetch_and
- AtomicPtr::fetch_xor
- {integer}::strict_add
- {integer}::strict_sub
- {integer}::strict_mul
- {integer}::strict_div
- {integer}::strict_div_euclid
- {integer}::strict_rem
- {integer}::strict_rem_euclid
- {integer}::strict_neg
- {integer}::strict_shl
- {integer}::strict_shr
- {integer}::strict_pow
- i{N}::strict_add_unsigned
- i{N}::strict_sub_unsigned
- i{N}::strict_abs
- u{N}::strict_add_signed
- u{N}::strict_sub_signed
- PanicHookInfo::payload_as_str
- core::iter::chain
- u{N}::checked_signed_diff
- core::array::repeat
- PathBuf::add_extension
- PathBuf::with_added_extension
- Duration::from_mins
- Duration::from_hours
- impl PartialEq for PathBuf
- impl PartialEq for PathBuf
- impl PartialEq for Path
- impl PartialEq for Path
- impl PartialEq for String
- impl PartialEq for String
- impl PartialEq for str
- impl PartialEq for str
- Ipv4Addr::from_octets
- Ipv6Addr::from_octets
- Ipv6Addr::from_segments
- impl Default for Pin<Box> where Box: Default, T: ?Sized
- impl Default for Pin<Rc> where Rc: Default, T: ?Sized
- impl Default for Pin<Arc> where Arc: Default, T: ?Sized
- Cell::as_array_of_cells
- u{N}::carrying_add
- u{N}::borrowing_sub
- u{N}::carrying_mul
- u{N}::carrying_mul_add
- BTreeMap::extract_if
- BTreeSet::extract_if
- impl Debug for windows::ffi::EncodeWide<'_>
- str::ceil_char_boundary
- str::floor_char_boundary
- impl Sum for Saturating<u{N}>
- impl Sum<&Self> for Saturating<u{N}>
- impl Product for Saturating<u{N}>
- impl Product<&Self> for Saturating<u{N}>
These previously stable APIs are now stable in const contexts:
- <[T; N]>::each_ref
- <[T; N]>::each_mut
- OsString::new
- PathBuf::new
- TypeId::of
- ptr::with_exposed_provenance
- ptr::with_exposed_provenance_mut
Platform Support
- Promote aarch64-pc-windows-msvc to Tier 1
- Promote aarch64-pc-windows-gnullvm and x86_64-pc-windows-gnullvm to Tier 2 with host tools. Note: llvm-tools and MSI installers are missing but will be added in future releases.
Refer to Rust’s platform support page for more information on Rust’s tiered platform support.
Other changes
Check out everything that changed in Rust, Cargo, and Clippy.
Contributors to 1.91.0
Many people came together to create Rust 1.91.0. We couldn't have done it without all of you.
Thanks!
Original source - Sep 18, 2025
- Date parsed from source:Sep 18, 2025
- First seen by Releasebot:May 23, 2026
Announcing Rust 1.90.0
Rust releases 1.90.0 with faster linking on x86_64-unknown-linux-gnu, native Cargo workspace publishing, and new stabilized APIs and const support. It also updates platform support by moving x86_64-apple-darwin to Tier 2.
The Rust team is happy to announce a new version of Rust, 1.90.0. Rust is a programming language empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via rustup, you can get 1.90.0 with:
$ rustup update stableIf you don't have it already, you can get rustup from the appropriate page on our website, and check out the detailed release notes for 1.90.0.
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 any bugs you might come across!
What's in 1.90.0 stable
LLD is now the default linker on x86_64-unknown-linux-gnu
LLD is now the default linker on x86_64-unknown-linux-gnu
The x86_64-unknown-linux-gnu target will now use the LLD linker for linking Rust crates by default. This should result in improved linking performance vs the default Linux linker (BFD), particularly for large binaries, binaries with a lot of debug information, and for incremental rebuilds.
In the vast majority of cases, LLD should be backwards compatible with BFD, and you should not see any difference other than reduced compilation time. However, if you do run into any new linker issues, you can always opt out using the -C linker-features=-lld compiler flag. Either by adding it to the usual RUSTFLAGS environment variable, or to a project's .cargo/config.toml configuration file, like so:
[target.x86_64-unknown-linux-gnu] rustflags = ["-Clinker-features=-lld"]If you encounter any issues with the LLD linker, please let us know. You can read more about the switch to LLD, some benchmark numbers and the opt out mechanism here.
Cargo adds native support for workspace publishing
cargo publish --workspace is now supported, automatically publishing all of the crates in a workspace in the right order (following any dependencies between them).
This has long been possible with external tooling or manual ordering of individual publishes, but this brings the functionality into Cargo itself.
Native integration allows Cargo's publish verification to run a build across the full set of to-be-published crates as if they were published, including during dry-runs. Note that publishes are still not atomic -- network errors or server-side failures can still lead to a partially published workspace.
Demoting x86_64-apple-darwin to Tier 2 with host tools
Demoting x86_64-apple-darwin to Tier 2 with host tools
GitHub will soon discontinue providing free macOS x86_64 runners for public repositories. Apple has also announced their plans for discontinuing support for the x86_64 architecture.
In accordance with these changes, as of Rust 1.90, we have demoted the x86_64-apple-darwin target from Tier 1 with host tools to Tier 2 with host tools. This means that the target, including tools like rustc and cargo, will be guaranteed to build but is not guaranteed to pass our automated test suite.
For users, this change will not immediately cause impact. Builds of both the standard library and the compiler will still be distributed by the Rust Project for use via rustup or alternative installation methods while the target remains at Tier 2. Over time, it's likely that reduced test coverage for this target will cause things to break or fall out of compatibility with no further announcements.
Stabilized APIs
u{n}::checked_sub_signedu{n}::overflowing_sub_signedu{n}::saturating_sub_signedu{n}::wrapping_sub_signedimpl Copy for IntErrorKindimpl Hash for IntErrorKindimpl PartialEq<&CStr> for CStrimpl PartialEq<CString> for CStrimpl PartialEq<Cow<CStr>> for CStrimpl PartialEq<&CStr> for CStringimpl PartialEq<CStr> for CStringimpl PartialEq<Cow<CStr>> for CStringimpl PartialEq<&CStr> for Cow<CStr>impl PartialEq<CStr> for Cow<CStr>impl PartialEq<CString> for Cow<CStr>
These previously stable APIs are now stable in const contexts:
<[T]>::reversef32::floorf32::ceilf32::truncf32::fractf32::roundf32::round_ties_evenf64::floorf64::ceilf64::truncf64::fractf64::roundf64::round_ties_even
Platform Support
x86_64-apple-darwinis now a tier 2 target
Refer to Rust’s platform support page for more information on Rust’s tiered platform support.
Other changes
Check out everything that changed in Rust, Cargo, and Clippy.
Contributors to 1.90.0
Many people came together to create Rust 1.90.0. We couldn't have done it without all of you. Thanks!
Original source - Aug 7, 2025
- Date parsed from source:Aug 7, 2025
- First seen by Releasebot:May 23, 2026
Rust 1.89.0
Rust ships 1.89.0 with new language ergonomics, broader x86 and wasm support, cross-compiled doctests, and more APIs stabilized for general use. It also adds clearer lifetime warnings and updates platform tiers for evolving hardware support.
The Rust team is happy to announce a new version of Rust, 1.89.0. Rust is a programming language empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via rustup, you can get 1.89.0 with:
$ rustup update stableIf you don't have it already, you can get rustup from the appropriate page on our website, and check out the detailed release notes for 1.89.0.
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 any bugs you might come across!
What's in 1.89.0 stable
Explicitly inferred arguments to const generics
Rust now supports _ as an argument to const generic parameters, inferring the value from surrounding context:
pub fn all_false<const LEN: usize>() -> [bool; LEN] { [false; _] }Similar to the rules for when _ is permitted as a type, _ is not permitted as an argument to const generics when in a signature:
// This is not allowed pub const fn all_false<const LEN: usize>() -> [bool; _] { [false; LEN] } // Neither is this pub const ALL_FALSE: [bool; _] = all_false::<10>();Mismatched lifetime syntaxes lint
Lifetime elision in function signatures is an ergonomic aspect of the Rust language, but it can also be a stumbling point for newcomers and experts alike. This is especially true when lifetimes are inferred in types where it isn't syntactically obvious that a lifetime is even present:
// The returned type `std::slice::Iter` has a lifetime, // but there's no visual indication of that. // // // Lifetime elision infers the lifetime of the return // type to be the same as that of `scores`. fn items(scores: &[u8]) -> std::slice::Iter<u8> { scores.iter() }Code like this will now produce a warning by default:
warning: hiding a lifetime that's elided elsewhere is confusing --> src/lib.rs:1:18 | 1 | fn items(scores: &[u8]) -> std::slice::Iter<u8> { | ^^^^^ -------------------- the same lifetime is hidden here | | | | | the lifetime is elided here | = help: the same lifetime is referred to in inconsistent ways, making the signature confusing = note: `#[warn(mismatched_lifetime_syntaxes)]` on by default help: use `'_` for type paths | 1 | fn items(scores: &[u8]) -> std::slice::Iter<'_, u8> { | +++We first attempted to improve this situation back in 2018 as part of the rust_2018_idioms lint group, but strong feedback about the elided_lifetimes_in_paths lint showed that it was too blunt of a hammer as it warns about lifetimes which don't matter to understand the function:
use std::fmt; struct Greeting; impl fmt::Display for Greeting { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // -----^^^^^^^^^ expected lifetime parameter // Knowing that `Formatter` has a lifetime does not help the programmer "howdy".fmt(f) } }We then realized that the confusion we want to eliminate occurs when both
- lifetime elision inference rules connect an input lifetime to an output lifetime
- it's not syntactically obvious that a lifetime exists
There are two pieces of Rust syntax that indicate that a lifetime exists: & and ', with ' being subdivided into the inferred lifetime '_ and named lifetimes 'a. When a type uses a named lifetime, lifetime elision will not infer a lifetime for that type. Using these criteria, we can construct three groups:
Self-evident it has a lifetime | Allow lifetime elision to infer a lifetime | Examples
No | Yes | ContainsLifetime
Yes | Yes | &T, &'_ T, ContainsLifetime<'_>
Yes | No | &'a T, ContainsLifetime<'a>The mismatched_lifetime_syntaxes lint checks that the inputs and outputs of a function belong to the same group. For the initial motivating example above, &[u8] falls into the second group while std::slice::Iter falls into the first group. We say that the lifetimes in the first group are hidden.
Because the input and output lifetimes belong to different groups, the lint will warn about this function, reducing confusion about when a value has a meaningful lifetime that isn't visually obvious.
The mismatched_lifetime_syntaxes lint supersedes the elided_named_lifetimes lint, which did something similar for named lifetimes specifically.
Future work on the elided_lifetimes_in_paths lint intends to split it into more focused sub-lints with an eye to warning about a subset of them eventually.
More x86 target features
The target_feature attribute now supports the sha512, sm3, sm4, kl and widekl target features on x86. Additionally a number of avx512 intrinsics and target features are also supported on x86:
#[target_feature(enable = "avx512bw")] pub fn cool_simd_code(/* .. */) -> /* ... */ { /* ... */ }Cross-compiled doctests
Doctests will now be tested when running cargo test --doc --target other_target, this may result in some amount of breakage due to would-be-failing doctests now being tested.
Failing tests can be disabled by annotating the doctest with ignore- (docs):
/// /// ```ignore-x86_64 /// panic!("something") /// ``` pub fn my_function() { }i128 and u128 in extern "C" functions
i128 and u128 in extern "C" functions no longer trigger the improper_ctypes_definitions lint, meaning these types may be used in extern "C" functions without warning. This comes with some caveats:
- The Rust types are ABI- and layout-compatible with (unsigned) __int128 in C when the type is available.
- On platforms where __int128 is not available, i128 and u128 do not necessarily align with any C type.
- i128 is not necessarily compatible with _BitInt(128) on any platform, because _BitInt(128) and __int128 may not have the same ABI (as is the case on x86-64).
This is the last bit of follow up to the layout changes from last year: https://blog.rust-lang.org/2024/03/30/i128-layout-update.
Demoting x86_64-apple-darwin to Tier 2 with host tools
Demoting x86_64-apple-darwin to Tier 2 with host tools
GitHub will soon discontinue providing free macOS x86_64 runners for public repositories. Apple has also announced their plans for discontinuing support for the x86_64 architecture.
In accordance with these changes, the Rust project is in the process of demoting the x86_64-apple-darwin target from Tier 1 with host tools to Tier 2 with host tools. This means that the target, including tools like rustc and cargo, will be guaranteed to build but is not guaranteed to pass our automated test suite.
We expect that the RFC for the demotion to Tier 2 with host tools will be accepted between the releases of Rust 1.89 and 1.90, which means that Rust 1.89 will be the last release of Rust where x86_64-apple-darwin is a Tier 1 target.
For users, this change will not immediately cause impact. Builds of both the standard library and the compiler will still be distributed by the Rust Project for use via rustup or alternative installation methods while the target remains at Tier 2. Over time, it's likely that reduced test coverage for this target will cause things to break or fall out of compatibility with no further announcements.
Standards Compliant C ABI on the wasm32-unknown-unknown target
Standards Compliant C ABI on the wasm32-unknown-unknown target
extern "C" functions on the wasm32-unknown-unknown target now have a standards compliant ABI. See this blog post for more information: https://blog.rust-lang.org/2025/04/04/c-abi-changes-for-wasm32-unknown-unknown.
Platform Support
- x86_64-apple-darwin is in the process of being demoted to Tier 2 with host tools
- Add new Tier-3 targets loongarch32-unknown-none and loongarch32-unknown-none-softfloat
Refer to Rust’s platform support page for more information on Rust’s tiered platform support.
Stabilized APIs
- NonZero
- Many intrinsics for x86, not enumerated here
- AVX512 intrinsics
- SHA512, SM3 and SM4 intrinsics
- File::lock
- File::lock_shared
- File::try_lock
- File::try_lock_shared
- File::unlock
- NonNull::from_ref
- NonNull::from_mut
- NonNull::without_provenance
- NonNull::with_exposed_provenance
- NonNull::expose_provenance
- OsString::leak
- PathBuf::leak
- Result::flatten
- std::os::linux::net::TcpStreamExt::quickack
- std::os::linux::net::TcpStreamExt::set_quickack
These previously stable APIs are now stable in const contexts:
- <[T; N]>::as_mut_slice
- <[u8]>::eq_ignore_ascii_case
- str::eq_ignore_ascii_case
Other changes
Check out everything that changed in Rust, Cargo, and Clippy.
Contributors to 1.89.0
Many people came together to create Rust 1.89.0. We couldn't have done it without all of you.
Original source - Jun 26, 2025
- Date parsed from source:Jun 26, 2025
- First seen by Releasebot:May 23, 2026
Announcing Rust 1.88.0
Rust releases 1.88.0 with let chains in Rust 2024, naked functions, boolean cfg literals, automatic Cargo cache cleaning, and a batch of stabilized APIs. It also updates target support and continues improving the language, tooling, and developer experience.
The Rust team is happy to announce a new version of Rust, 1.88.0. Rust is a programming language empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via rustup, you can get 1.88.0 with:
$ rustup update stableIf you don't have it already, you can get rustup from the appropriate page on our website, and check out the detailed release notes for 1.88.0.
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 any bugs you might come across!
What's in 1.88.0 stable
Let chains
This feature allows &&-chaining let statements inside if and while conditions, even intermingling with boolean expressions, so there is less distinction between if / if let and while / while let. The patterns inside the let sub-expressions can be irrefutable or refutable, and bindings are usable in later parts of the chain as well as the body.
For example, this snippet combines multiple conditions which would have required nesting if let and if blocks before:
if let Channel::Stable(v) = release_info() && let Semver { major, minor, .. } = v && major == 1 && minor == 88 { println!("`let_chains` was stabilized in this version"); }Let chains are only available in the Rust 2024 edition, as this feature depends on the if let temporary scope change for more consistent drop order.
Earlier efforts tried to work with all editions, but some difficult edge cases threatened the integrity of the implementation. 2024 made it feasible, so please upgrade your crate's edition if you'd like to use this feature!
Naked functions
Rust now supports writing naked functions with no compiler-generated epilogue and prologue, allowing full control over the generated assembly for a particular function. This is a more ergonomic alternative to defining functions in a global_asm! block. A naked function is marked with the #[unsafe(naked)] attribute, and its body consists of a single naked_asm! call.
For example:
#[unsafe(naked)] pub unsafe extern "sysv64" fn wrapping_add(a: u64, b: u64) -> u64 { // Equivalent to `a.wrapping_add(b)`. core::arch::naked_asm!("lea rax, [rdi + rsi]", "ret"); }The handwritten assembly block defines the entire function body: unlike non-naked functions, the compiler does not add any special handling for arguments or return values. Naked functions are used in low-level settings like Rust's compiler-builtins, operating systems, and embedded applications.
Look for a more detailed post on this soon!
Boolean configuration
The cfg predicate language now supports boolean literals, true and false, acting as a configuration that is always enabled or disabled, respectively. This works in Rust conditional compilation with cfg and cfg_attr attributes and the built-in cfg! macro, and also in Cargo [target] tables in both configuration and manifests.
Previously, empty predicate lists could be used for unconditional configuration, like cfg(all()) for enabled and cfg(any()) for disabled, but this meaning is rather implicit and easy to get backwards. cfg(true) and cfg(false) offer a more direct way to say what you mean.
See RFC 3695 for more background!
Cargo automatic cache cleaning
Starting in 1.88.0, Cargo will automatically run garbage collection on the cache in its home directory!
When building, Cargo downloads and caches crates needed as dependencies. Historically, these downloaded files would never be cleaned up, leading to an unbounded amount of disk usage in Cargo's home directory. In this version, Cargo introduces a garbage collection mechanism to automatically clean up old files (e.g. .crate files). Cargo will remove files downloaded from the network if not accessed in 3 months, and files obtained from the local system if not accessed in 1 month. Note that this automatic garbage collection will not take place if running offline (using --offline or --frozen).
Cargo 1.78 and newer track the access information needed for this garbage collection. This was introduced well before the actual cleanup that's starting now, in order to reduce cache churn for those that still use prior versions. If you regularly use versions of Cargo even older than 1.78, in addition to running current versions of Cargo, and you expect to have some crates accessed exclusively by the older versions of Cargo and don't want to re-download those crates every ~3 months, you may wish to set cache.auto-clean-frequency = "never" in the Cargo configuration, as described in the docs.
For more information, see the original unstable announcement of this feature. Some parts of that design remain unstable, like the gc subcommand tracked in cargo#13060, so there's still more to look forward to!
Stabilized APIs
- Cell::update
- impl Default for *const T
- impl Default for *mut T
- mod ffi::c_str
- HashMap::extract_if
- HashSet::extract_if
- hint::select_unpredictable
- proc_macro::Span::line
- proc_macro::Span::column
- proc_macro::Span::start
- proc_macro::Span::end
- proc_macro::Span::file
- proc_macro::Span::local_file
- <[T]>::as_chunks
- <[T]>::as_rchunks
- <[T]>::as_chunks_unchecked
- <[T]>::as_chunks_mut
- <[T]>::as_rchunks_mut
- <[T]>::as_chunks_unchecked_mut
These previously stable APIs are now stable in const contexts:
- NonNull::replace
- <*mut T>::replace
- std::ptr::swap_nonoverlapping
- Cell::replace
- Cell::get
- Cell::get_mut
- Cell::from_mut
- Cell::as_slice_of_cells
Other changes
The i686-pc-windows-gnu target has been demoted to Tier 2, as mentioned in an earlier post. This won't have any immediate effect for users, since both the compiler and standard library tools will still be distributed by rustup for this target. However, with less testing than it had at Tier 1, it has more chance of accumulating bugs in the future.
Check out everything that changed in Rust, Cargo, and Clippy.
Contributors to 1.88.0
Many people came together to create Rust 1.88.0. We couldn't have done it without all of you.
Original source - May 15, 2025
- Date parsed from source:May 15, 2025
- First seen by Releasebot:May 23, 2026
Announcing Rust 1.87.0 and ten years of Rust!
Rust releases 1.87.0 with anniversary momentum, adding anonymous pipes, safer std::arch intrinsics, asm! jumps to Rust code, and precise capturing in trait definitions. It also stabilizes more APIs in const contexts and removes the i586-pc-windows-msvc target.
Live from the 10 Years of Rust celebration in Utrecht, Netherlands, the Rust team is happy to announce a new version of Rust, 1.87.0!
Today's release day happens to fall exactly on the 10 year anniversary of Rust 1.0!
Thank you to the myriad contributors who have worked on Rust, past and present. Here's to many more decades of Rust! 🎉
As usual, the new version includes all the changes that have been part of the beta version in the past six weeks, following the consistent regular release cycle that we have followed since Rust 1.0.
If you have a previous version of Rust installed via rustup, you can get 1.87.0 with:
$ rustup update stableIf you don't have it already, you can get rustup from the appropriate page on our website, and check out the detailed release notes for 1.87.0.
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 any bugs you might come across!
What's in 1.87.0 stable
Anonymous pipes
1.87 adds access to anonymous pipes to the standard library. This includes integration with std::process::Command's input/output methods. For example, joining the stdout and stderr streams into one is now relatively straightforward, as shown below, while it used to require either extra threads or platform-specific functions.
Safe architecture intrinsics
Most std::arch intrinsics that are unsafe only due to requiring target features to be enabled are now callable in safe code that has those features enabled. For example, the following toy program which implements summing an array using manual intrinsics can now use safe code for the core loop.
asm! jumps to Rust code
Inline assembly (asm!) can now jump to labeled blocks within Rust code. This enables more flexible low-level programming, such as implementing optimized control flow in OS kernels or interacting with hardware more efficiently.
- The asm! macro now supports a label operand, which acts as a jump target.
- The label must be a block expression with a return type of () or !.
- The block executes when jumped to, and execution continues after the asm! block.
- Using output and label operands in the same asm! invocation remains unstable.
For more details, please consult the reference.
Precise capturing (+ use<...>) in impl Trait in trait definitions
This release stabilizes specifying the specific captured generic types and lifetimes in trait definitions using impl Trait return types. This allows using this feature in trait definitions, expanding on the stabilization for non-trait functions in 1.82.
Some example desugarings:
Stabilized APIs
These previously stable APIs are now stable in const contexts:
- Vec::extract_if
- vec::ExtractIf
- LinkedList::extract_if
- linked_list::ExtractIf
- <[T]>::split_off
- <[T]>::split_off_mut
- <[T]>::split_off_first
- <[T]>::split_off_first_mut
- <[T]>::split_off_last
- <[T]>::split_off_last_mut
- String::extend_from_within
- os_str::Display
- OsString::display
- OsStr::display
- io::pipe
- io::PipeReader
- io::PipeWriter
- impl From for OwnedHandle
- impl From for OwnedHandle
- impl From for Stdio
- impl From for Stdio
- impl From for OwnedFd
- impl From for OwnedFd
- Box<MaybeUninit>::write
- impl TryFrom<Vec> for String
- <*const T>::offset_from_unsigned
- <*const T>::byte_offset_from_unsigned
- <*mut T>::offset_from_unsigned
- <*mut T>::byte_offset_from_unsigned
- NonNull::offset_from_unsigned
- NonNull::byte_offset_from_unsigned
- ::cast_signed
- NonZero::::cast_signed.
- ::cast_unsigned.
- NonZero::::cast_unsigned.
- ::is_multiple_of
- ::unbounded_shl
- ::unbounded_shr
- ::unbounded_shl
- ::unbounded_shr
- ::midpoint
- ::from_utf8
- ::from_utf8_mut
- ::from_utf8_unchecked
- ::from_utf8_unchecked_mut
i586-pc-windows-msvc target removal
The Tier 2 target i586-pc-windows-msvc has been removed. i586-pc-windows-msvc's difference to the much more popular Tier 1 target i686-pc-windows-msvc is that i586-pc-windows-msvc does not require SSE2 instruction support. But Windows 10, the minimum required OS version of all windows targets (except the win7 targets), requires SSE2 instructions itself.
All users currently targeting i586-pc-windows-msvc should migrate to i686-pc-windows-msvc.
You can check the Major Change Proposal for more information.
Other changes
Check out everything that changed in Rust, Cargo, and Clippy.
Contributors to 1.87.0
Many people came together to create Rust 1.87.0. We couldn't have done it without all of you.
Original source - Apr 3, 2025
- Date parsed from source:Apr 3, 2025
- First seen by Releasebot:May 23, 2026
Announcing Rust 1.86.0
Rust releases 1.86.0 with long-awaited trait upcasting, disjoint mutable indexing for slices and HashMaps, safer target_feature support for safe functions, stronger debug null-pointer checks, and a batch of stabilized APIs.
The Rust team is happy to announce a new version of Rust, 1.86.0. Rust is a programming language empowering everyone to build reliable and efficient software.
If you have a previous version of Rust installed via rustup, you can get 1.86.0 with:
$ rustup update stableIf you don't have it already, you can get rustup from the appropriate page on our website, and check out the detailed release notes for 1.86.0.
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 any bugs you might come across!
What's in 1.86.0 stable
Trait upcasting
This release includes a long awaited feature — the ability to upcast trait objects. If a trait has a supertrait you can coerce a reference to said trait object to a reference to a trait object of the supertrait:
trait Trait : Supertrait {} trait Supertrait {} fn upcast(x: &dyn Trait) -> &dyn Supertrait { x }The same would work with any other kind of (smart-)pointer, like Arc -> Arc or *const dyn Trait -> *const dyn Supertrait.
Previously this would have required a workaround in the form of an upcast method in the Trait itself, for example fn as_supertrait(&self) -> &dyn Supertrait, and this would work only for one kind of reference/pointer. Such workarounds are not necessary anymore.
Note that this means that raw pointers to trait objects carry a non-trivial invariant: "leaking" a raw pointer to a trait object with an invalid vtable into safe code may lead to undefined behavior. It is not decided yet whether creating such a raw pointer temporarily in well-controlled circumstances causes immediate undefined behavior, so code should refrain from creating such pointers under any conditions (and Miri enforces that).
Trait upcasting may be especially useful with the Any trait, as it allows upcasting your trait object to dyn Any to call Any's downcast methods, without adding any trait methods or using external crates.
use std::any::Any; trait MyAny : Any {} impl dyn MyAny { fn downcast_ref<T>(&self) -> Option<&T> { (self as &dyn Any).downcast_ref() } }You can learn more about trait upcasting in the Rust reference.
HashMaps and slices now support indexing multiple elements mutably
The borrow checker prevents simultaneous usage of references obtained from repeated calls to get_mut methods. To safely support this pattern the standard library now provides a get_disjoint_mut helper on slices and HashMap to retrieve mutable references to multiple elements simultaneously. See the following example taken from the API docs of slice::get_disjoint_mut :
let v = &mut [1, 2, 3]; if let Ok([a, b]) = v.get_disjoint_mut([0, 2]) { *a = 413; *b = 612; } assert_eq!(v, &[413, 2, 612]); if let Ok([a, b]) = v.get_disjoint_mut([0..1, 1..3]) { a[0] = 8; b[0] = 88; b[1] = 888; } assert_eq!(v, &[8, 88, 888]); if let Ok([a, b]) = v.get_disjoint_mut([1..=2, 0..=0]) { a[0] = 11; a[1] = 111; b[0] = 1; } assert_eq!(v, &[1, 11, 111]);Allow safe functions to be marked with the #[target_feature] attribute.
Previously only unsafe functions could be marked with the #[target_feature] attribute as it is unsound to call such functions without the target feature being enabled. This release stabilizes the target_feature_11 feature, allowing safe functions to be marked with the #[target_feature] attribute.
Safe functions marked with the target feature attribute can only be safely called from other functions marked with the target feature attribute. However, they cannot be passed to functions accepting generics bounded by the Fn* traits and only support being coerced to function pointers inside of functions marked with the target_feature attribute.
Inside of functions not marked with the target feature attribute they can be called inside of an unsafe block, however it is the caller's responsibility to ensure that the target feature is available.
# [target_feature(enable = "avx2")] fn requires_avx2() { // ... snip } # [target_feature(enable = "avx2")] fn safe_callsite() { // Calling `requires_avx2` here is safe as `safe_callsite` // requires the `avx2` feature itself. requires_avx2(); } fn unsafe_callsite() { // Calling `requires_avx2` here is unsafe, as we must // ensure that the `avx2` feature is available first. if is_x86_feature_detected!("avx2") { unsafe { requires_avx2(); }; } }You can check the target_features_11 RFC for more information.
Debug assertions that pointers are non-null when required for soundness
The compiler will now insert debug assertions that a pointer is not null upon non-zero-sized reads and writes, and also when the pointer is reborrowed into a reference. For example, the following code will now produce a non-unwinding panic when debug assertions are enabled:
let _x = *std::ptr::null::<u8>(); let _x = &*std::ptr::null::<u8>();Trivial examples like this have produced a warning since Rust 1.53.0, the new runtime check will detect these scenarios regardless of complexity.
These assertions only take place when debug assertions are enabled which means that they must not be relied upon for soundness. This also means that dependencies which have been compiled with debug assertions disabled (e.g. the standard library) will not trigger the assertions even when called by code with debug assertions enabled.
Make missing_abi lint warn by default
Omitting the ABI in extern blocks and functions (e.g. extern {} and extern fn) will now result in a warning (via the missing_abi lint). Omitting the ABI after the extern keyword has always implicitly resulted in the "C" ABI. It is now recommended to explicitly specify the "C" ABI (e.g. extern "C" {} and extern "C" fn).
You can check the Explicit Extern ABIs RFC for more information.
Target deprecation warning for 1.87.0
The tier-2 target i586-pc-windows-msvc will be removed in the next version of Rust, 1.87.0. Its difference to the much more popular i686-pc-windows-msvc is that it does not require SSE2 instruction support, but Windows 10, the minimum required OS version of all windows targets (except the win7 targets), requires SSE2 instructions itself.
All users currently targeting i586-pc-windows-msvc should migrate to i686-pc-windows-msvc before the 1.87.0 release.
You can check the Major Change Proposal for more information.
Stabilized APIs
- {float}::next_down
- {float}::next_up
- <[_]>::get_disjoint_mut
- <[_]>::get_disjoint_unchecked_mut
- slice::GetDisjointMutError
- HashMap::get_disjoint_mut
- HashMap::get_disjoint_unchecked_mut
- NonZero::count_ones
- Vec::pop_if
- sync::Once::wait
- sync::Once::wait_force
- sync::OnceLock::wait
These APIs are now stable in const contexts:
- hint::black_box
- io::Cursor::get_mut
- io::Cursor::set_position
- str::is_char_boundary
- str::split_at
- str::split_at_checked
- str::split_at_mut
- str::split_at_mut_checked
Other changes
Check out everything that changed in Rust, Cargo, and Clippy.
Contributors to 1.86.0
Many people came together to create Rust 1.86.0. We couldn't have done it without all of you.
Thanks!
Original source
Curated by the Releasebot team
Releasebot is an aggregator of official release notes from hundreds of software vendors and thousands of sources.
Our editorial process involves the manual review and audit of release notes procured with the help of automated systems.
Similar to Rust with recent updates:
- Salesforce release notes14 release notes · Latest May 1, 2026
- Zoom release notes164 release notes · Latest Jun 1, 2026
- Hubspot release notes119 release notes · Latest Jun 3, 2026
- Slack release notes155 release notes · Latest Jun 1, 2026
- Grammarly release notes4 release notes · Latest Jan 31, 2026
- Anthropic release notes604 release notes · Latest Jun 6, 2026