|
| 1 | ++++ |
| 2 | +path = "2025/08/07/Rust-1.89.0" |
| 3 | +title = "Announcing Rust 1.89.0" |
| 4 | +authors = ["The Rust Release Team"] |
| 5 | +aliases = ["releases/1.89.0"] |
| 6 | + |
| 7 | +[extra] |
| 8 | +release = true |
| 9 | ++++ |
| 10 | + |
| 11 | +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. |
| 12 | + |
| 13 | +If you have a previous version of Rust installed via `rustup`, you can get 1.89.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.89.0](https://doc.rust-lang.org/stable/releases.html#version-1890-2025-08-07). |
| 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.89.0 stable |
| 24 | + |
| 25 | +### Explicitly inferred arguments to const generics |
| 26 | + |
| 27 | +Rust now supports `_` as an argument to const generic parameters, inferring the value from surrounding context: |
| 28 | + |
| 29 | +```rust |
| 30 | +pub fn make_bitset<const LEN: usize>() -> [bool; LEN] { |
| 31 | + [false; _] |
| 32 | +} |
| 33 | +``` |
| 34 | + |
| 35 | +Similar to the rules for when `_` is permitted as a type, `_` is not permitted as an argument to const generics when in a signature: |
| 36 | + |
| 37 | +```rust |
| 38 | +// This is not allowed |
| 39 | +pub const fn make_bitset<const LEN: usize>() -> [bool; _] { |
| 40 | + [false; LEN] |
| 41 | +} |
| 42 | +// Neither is this |
| 43 | +pub const MY_BITSET: [bool; _] = make_bitset::<10>(); |
| 44 | +``` |
| 45 | + |
| 46 | +### Mismatched lifetime syntaxes lint |
| 47 | + |
| 48 | +[Lifetime elision][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: |
| 49 | + |
| 50 | +```rust |
| 51 | +// The returned type `std::slice::Iter` has a lifetime, |
| 52 | +// but there's no visual indication of that. |
| 53 | +// |
| 54 | +// Lifetime elision infers the lifetime of the return |
| 55 | +// value to be the same as the argument `scores`. |
| 56 | +fn items(scores: &[u8]) -> std::slice::Iter<u8> { |
| 57 | + scores.iter() |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +Code like this will now produce a warning by default: |
| 62 | + |
| 63 | +```text |
| 64 | +warning: hiding a lifetime that's elided elsewhere is confusing |
| 65 | + --> src/lib.rs:1:18 |
| 66 | + | |
| 67 | +1 | fn items(scores: &[u8]) -> std::slice::Iter<u8> { |
| 68 | + | ^^^^^ -------------------- the same lifetime is hidden here |
| 69 | + | | |
| 70 | + | the lifetime is elided here |
| 71 | + | |
| 72 | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing |
| 73 | + = note: `#[warn(mismatched_lifetime_syntaxes)]` on by default |
| 74 | +help: use `'_` for type paths |
| 75 | + | |
| 76 | +1 | fn items(scores: &[u8]) -> std::slice::Iter<'_, u8> { |
| 77 | + | +++ |
| 78 | +``` |
| 79 | + |
| 80 | +We [first attempted][elided_lifetime_in_path] to improve this situation back in 2018 as part of the [`rust_2018_idioms`][2018-by-default] lint group, but [strong feedback][bevy] 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: |
| 81 | + |
| 82 | +```rust |
| 83 | +use std::fmt; |
| 84 | + |
| 85 | +struct Greeting; |
| 86 | + |
| 87 | +impl fmt::Display for Greeting { |
| 88 | + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| 89 | + // -----^^^^^^^^^ expected lifetime parameter |
| 90 | + // Knowing that `Formatter` has a lifetime does not help the programmer |
| 91 | + "howdy".fmt(f) |
| 92 | + } |
| 93 | +} |
| 94 | +``` |
| 95 | + |
| 96 | +We then realized that the confusion we want to eliminate occurs when both |
| 97 | + |
| 98 | +1. lifetime elision inference rules *connect* an input lifetime to an output lifetime |
| 99 | +2. it's not syntactically obvious that a lifetime exists |
| 100 | + |
| 101 | +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: |
| 102 | + |
| 103 | +| Self-evident it has a lifetime | Allow lifetime elision to infer a lifetime | Examples | |
| 104 | +|--------------------------------|--------------------------------------------|---------------------------------------| |
| 105 | +| No | Yes | `ContainsLifetime` | |
| 106 | +| Yes | Yes | `&T`, `&'_ T`, `ContainsLifetime<'_>` | |
| 107 | +| Yes | No | `&'a T`, `ContainsLifetime<'a>` | |
| 108 | + |
| 109 | +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<u8>` falls into the first group. We say that the lifetimes in the first group are *hidden*. |
| 110 | + |
| 111 | +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. |
| 112 | + |
| 113 | +The `mismatched_lifetime_syntaxes` lint supersedes the `elided_named_lifetimes` lint, which did something similar for named lifetimes specifically. |
| 114 | + |
| 115 | +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. |
| 116 | + |
| 117 | +[elision]: https://doc.rust-lang.org/1.89/book/ch10-03-lifetime-syntax.html#lifetime-elision |
| 118 | +[elided_lifetime_in_path]: https://github.com/rust-lang/rust/pull/46254 |
| 119 | +[2018-by-default]: https://github.com/rust-lang/rust/issues/54910 |
| 120 | +[bevy]: https://github.com/rust-lang/rust/issues/131725 |
| 121 | + |
| 122 | +### More x86 target features |
| 123 | + |
| 124 | +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: |
| 125 | + |
| 126 | +```rust |
| 127 | +#[target_feature(enable = "avx512bw")] |
| 128 | +pub fn cool_simd_code(/* .. */) -> /* ... */ { |
| 129 | + /* ... */ |
| 130 | +} |
| 131 | + |
| 132 | +``` |
| 133 | + |
| 134 | +### Platform Support |
| 135 | + |
| 136 | +- [Add new Tier-3 targets `loongarch32-unknown-none` and `loongarch32-unknown-none-softfloat`](https://github.com/rust-lang/rust/pull/142053) |
| 137 | + |
| 138 | +Refer to Rust’s [platform support page][platform_support_page] for more information on Rust’s tiered platform support. |
| 139 | + |
| 140 | +### Stabilized APIs |
| 141 | + |
| 142 | +- [`NonZero<char>`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html) |
| 143 | +- Many intrinsics for x86, not enumerated here |
| 144 | + - [AVX512 intrinsics](https://github.com/rust-lang/rust/issues/111137) |
| 145 | + - [`SHA512`, `SM3` and `SM4` intrinsics](https://github.com/rust-lang/rust/issues/126624) |
| 146 | +- [`File::lock`](https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.lock) |
| 147 | +- [`File::lock_shared`](https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.lock_shared) |
| 148 | +- [`File::try_lock`](https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.try_lock) |
| 149 | +- [`File::try_lock_shared`](https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.try_lock_shared) |
| 150 | +- [`File::unlock`](https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.unlock) |
| 151 | +- [`NonNull::from_ref`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.from_ref) |
| 152 | +- [`NonNull::from_mut`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.from_mut) |
| 153 | +- [`NonNull::without_provenance`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.without_provenance) |
| 154 | +- [`NonNull::with_exposed_provenance`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.with_exposed_provenance) |
| 155 | +- [`NonNull::expose_provenance`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.expose_provenance) |
| 156 | +- [`OsString::leak`](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.leak) |
| 157 | +- [`PathBuf::leak`](https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#method.leak) |
| 158 | +- [`Result::flatten`](https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.flatten) |
| 159 | +- [`std::os::linux::net::TcpStreamExt::quickack`](https://doc.rust-lang.org/stable/std/os/linux/net/trait.TcpStreamExt.html#tymethod.quickack) |
| 160 | +- [`std::os::linux::net::TcpStreamExt::set_quickack`](https://doc.rust-lang.org/stable/std/os/linux/net/trait.TcpStreamExt.html#tymethod.set_quickack) |
| 161 | + |
| 162 | +These previously stable APIs are now stable in const contexts: |
| 163 | + |
| 164 | +- [`<[T; N]>::as_mut_slice`](https://doc.rust-lang.org/stable/std/primitive.array.html#method.as_mut_slice) |
| 165 | +- [`<[u8]>::eq_ignore_ascii_case`](https://doc.rust-lang.org/stable/std/primitive.slice.html#impl-%5Bu8%5D/method.eq_ignore_ascii_case) |
| 166 | +- [`str::eq_ignore_ascii_case`](https://doc.rust-lang.org/stable/std/primitive.str.html#impl-str/method.eq_ignore_ascii_case) |
| 167 | + |
| 168 | +### Other changes |
| 169 | + |
| 170 | +Check out everything that changed in [Rust](https://github.com/rust-lang/rust/releases/tag/1.89.0), [Cargo](https://doc.rust-lang.org/nightly/cargo/CHANGELOG.html#cargo-189-2025-08-07), and [Clippy](https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-189). |
| 171 | + |
| 172 | +## Contributors to 1.89.0 |
| 173 | + |
| 174 | +Many people came together to create Rust 1.89.0. We couldn't have done it without all of you. [Thanks!](https://thanks.rust-lang.org/rust/1.89.0/) |
| 175 | + |
| 176 | +[platform_support_page]: https://doc.rust-lang.org/rustc/platform-support.html |
0 commit comments