Rust versions / 1.98
Rust release · Aug 20, 2026
Rust 1.98: what's new, what was stabilized
Short answerRust 1.98 was released on Aug 20, 2026: 23 newly stable APIs (str::substr_range, [T]::subslice_range, core::fmt::NumBuffer, <{integer}>::format_into, ...); 18 compatibility notes that can affect existing code. Point release: 1.98.1 (Sep 3, 2026).
← Rust 1.97All versionsRust 1.99 →
23 APIs stabilized
str::substr_range, [T]::subslice_range, core::fmt::NumBuffer, <{integer}>::format_into, Send/Sync for std::process::CommandArgs, {fN}::algebraic_add, {fN}::algebraic_sub, {fN}::algebraic_mul, {fN}::algebraic_div, {fN}::algebraic_rem, NonZero<{integer}>::from_str_radix, String::from_utf16le, String::from_utf16le_lossy, String::from_utf16be, String::from_utf16be_lossy, [T]::strip_circumfix, str::strip_circumfix, Atomic<T>::from_mut, Atomic<T>::get_mut_slice, Atomic<T>::from_mut_slice, std::range::legacy, bool::ok_or, bool::ok_or_else
Can it break my build?
The release lists these compatibility notes. Most only affect rare code, but read them before you raise your toolchain in CI:
- If fully elided, lifetime bounds of trait object types may now resolve differently or even get rejected in very specific niche scenarios
- Error in more cases of ambiguous imports
- Switch the destructors implementation for thread locals on Windows to use Fiber Local Storage (FLS)
- Convert some cases of the
ambiguous_glob_importslint into a hard error - Where-bounds of the form
Type = TypeandType == Typeare no longer syntactically allowed - Ensure Send/Sync is not implemented for std::env::Vars{,Os}
- Fix that in some attributes, arguments were not properly rejected
- [
repr(transparent)is now more strict about which fields have "trivial" layout and hence can be ignored:repr(C)types, types with private fields, and#[non_exhaustive]types are no longer considered "trivial"](https://github.com/rust-lang/rust/pull/155299) - Correctly check whether types have equal size in
transmute()when somereprattributes are involved. - More characters are escaped when printing strings and chars
- Implement fast path for
derive(PartialOrd)when derivingOrd - Add temporary scope to
assert_eqandassert_ne - Closed a hole in the pattern matching structural equality check, preventing cases where a match of a constant would be allowed, despite disagreeing with a manually written
PartialEqimplementation, when aderive(PartialEq)implementation for that type also exists. - On Emscripten the WASM exception handling ABI is now unconditionally used The
-Zemscripten-wasm-eh=falseflag to switch back to JS exceptions has been removed. - The UNSAFE_CODE lint is now consistently emitted for all unsafe attributes
- Solaris: remove
File::lockimplementation, it has the wrong semantics (return "unsupported" instead) - Windows-gnu targets now specify baseline tools versions
- rustfmt now discovers module files that are defined in
cfg_select!
Use it
rustup update stable # get the newest release
rustup install 1.98 # or exactly this one
rustup override set 1.98 # pin a project to itTo require at least this version from users of your crate, set rust-version = "1.98" under [package] in Cargo.toml. Cargo then refuses to build it on older compilers with a clear message, and with resolver 3 (the default on the 2024 edition, Rust 1.85+) it also prefers dependency versions that support it.
Full release notes
Language
- Allow shortening lifetime of
&mutwhen unsize-coercing, even in an invariant position. For example, you can now coerce aCell<&'long mut i32>to aCell<&'short mut dyn Send>. Such shortenings were already previously allowed when coercing a&mutto a&, or coercing a&to a&. - Add deny-by-default
invalid_runtime_symbol_definitionslint and warn-by-defaultsuspicious_runtime_symbol_definitionslint - The lints currently specifically targets
coreruntime symbols likememcmp,memset,strlen, ... and is planned to be expanded in the next few releases. - Add warn-by-default
c_void_returnslint to checkcore::ffi::c_voidas a return type
<a id="1.98.0-Platform-Support"></a>
Platform Support
- Add
powerpc64-unknown-linux-gnuelfv2as Tier 3 - Add
aarch64-unknown-linux-pauthtestas Tier 3 target - Promote
thumbv7a-none-eabito Tier 2 - Promote
thumbv7a-none-eabihfto Tier 2 - Promote
thumbv7r-none-eabito Tier 2 - Promote
thumbv7r-none-eabihfto Tier 2 - Promote
thumbv8r-none-eabihfto Tier 2
Refer to Rust's platform support page for more information on Rust's tiered platform support.
<a id="1.98.0-Libraries"></a>
Libraries
- [Change
Location<'_>lifetime to'staticinPanic[Hook]Info](https://github.com/rust-lang/rust/pull/146561) - Document panic in
RangeInclusive::from(legacy::RangeInclusive) - Document that
ManuallyDrop'sBoxinteraction has been fixed - Stabilize LoongArch CRC Intrinsics
- The
derivemacro is available at{core,std}::derive. This was previously unintentionally stabilized in 1.96, but is now explicitly accepted as a stabilized API. - Please note that the MSRV for
{core,std}::derivewill be 1.96, and not 1.98.
<a id="1.98.0-Stabilized-APIs"></a>
Stabilized APIs
str::substr_range- [
[T]::subslice_range](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.subslice_range) core::fmt::NumBuffer<{integer}>::format_intoSend/Sync for std::process::CommandArgs{fN}::algebraic_add{fN}::algebraic_sub{fN}::algebraic_mul{fN}::algebraic_div{fN}::algebraic_remNonZero<{integer}>::from_str_radixString::from_utf16leString::from_utf16le_lossyString::from_utf16beString::from_utf16be_lossy- [
[T]::strip_circumfix](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.strip_circumfix) str::strip_circumfixAtomic<T>::from_mutAtomic<T>::get_mut_sliceAtomic<T>::from_mut_slicestd::range::legacybool::ok_orbool::ok_or_else
<a id="1.98.0-Compatibility-Notes"></a>
Compatibility Notes
- If fully elided, lifetime bounds of trait object types may now resolve differently or even get rejected in very specific niche scenarios
- Error in more cases of ambiguous imports
- Switch the destructors implementation for thread locals on Windows to use Fiber Local Storage (FLS)
- Convert some cases of the
ambiguous_glob_importslint into a hard error - Where-bounds of the form
Type = TypeandType == Typeare no longer syntactically allowed - Ensure Send/Sync is not implemented for std::env::Vars{,Os}
- Fix that in some attributes, arguments were not properly rejected
- [
repr(transparent)is now more strict about which fields have "trivial" layout and hence can be ignored:repr(C)types, types with private fields, and#[non_exhaustive]types are no longer considered "trivial"](https://github.com/rust-lang/rust/pull/155299) - Correctly check whether types have equal size in
transmute()when somereprattributes are involved. - More characters are escaped when printing strings and chars
- Implement fast path for
derive(PartialOrd)when derivingOrdThis can break crates in practice where a type's PartialOrd and Ord impls were inconsistent with each other. - Add temporary scope to
assert_eqandassert_ne - Closed a hole in the pattern matching structural equality check, preventing cases where a match of a constant would be allowed, despite disagreeing with a manually written
PartialEqimplementation, when aderive(PartialEq)implementation for that type also exists. - On Emscripten the WASM exception handling ABI is now unconditionally used The
-Zemscripten-wasm-eh=falseflag to switch back to JS exceptions has been removed. - The UNSAFE_CODE lint is now consistently emitted for all unsafe attributes
- Solaris: remove
File::lockimplementation, it has the wrong semantics (return "unsupported" instead) - Windows-gnu targets now specify baseline tools versions
- rustfmt now discovers module files that are defined in
cfg_select!This may cause more code to be formatted which was previously ignored.
1.98.1 (Sep 3, 2026)
<a id="1.98.1"></a>
Release notes from the Rust project's RELEASES.md (MIT or Apache-2.0); summaries above are ours.
Up next
Next releaseRust 1.99Released Oct 1, 2026.Read it next →Also worth your time
Did this answer your question?