|
| 1 | ++++ |
| 2 | +layout = "post" |
| 3 | +date = 2025-04-03 |
| 4 | +title = "Announcing Rust 1.86.0" |
| 5 | +author = "The Rust Release Team" |
| 6 | +release = true |
| 7 | ++++ |
| 8 | + |
| 9 | +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. |
| 10 | + |
| 11 | +If you have a previous version of Rust installed via `rustup`, you can get 1.86.0 with: |
| 12 | + |
| 13 | +```console |
| 14 | +$ rustup update stable |
| 15 | +``` |
| 16 | + |
| 17 | +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.86.0](https://doc.rust-lang.org/stable/releases.html#version-1860-2025-04-03). |
| 18 | + |
| 19 | +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! |
| 20 | + |
| 21 | +## What's in 1.86.0 stable |
| 22 | + |
| 23 | +### Trait upcasting |
| 24 | + |
| 25 | +This release includes a long awaited feature — the ability to upcast trait objects. |
| 26 | +If a trait has a [supertrait](https://doc.rust-lang.org/reference/items/traits.html#supertraits) you can coerce a reference to said trait object to a reference to a trait object of the super trait: |
| 27 | + |
| 28 | +```rust |
| 29 | +trait Trait: Supertrait {} |
| 30 | +trait Supertrait {} |
| 31 | + |
| 32 | +fn upcast(x: &dyn Trait) -> &dyn Supertrait { |
| 33 | + x |
| 34 | +} |
| 35 | +``` |
| 36 | + |
| 37 | +The same would work with any other kind of (smart)-pointer, like `Arc<dyn Trait> -> Arc<dyn Supertrait>` or `*const dyn Trait -> *const dyn Supertrait`. |
| 38 | + |
| 39 | +Previously this would require a workaround in the form of an `upcast` method in the `Trait` itself (and that would work only for one kind of reference/pointer). Such workarounds are not necessary anymore. |
| 40 | + |
| 41 | +Note that this adds a new _safety invariant_ to raw pointers — if a pointer points to a trait object, vtable must be valid for that trait. This means that "leaking" a raw pointer to a trait object with an invalid vtable into safe code may lead to undefined behavior. |
| 42 | + |
| 43 | +Trait upcasting may be especially useful with the `Any` trait, as it allows upcasting your trait object to `dyn Any` to call the downcast methods. Whereas before you'd have to write workarounds for this or use external crates. |
| 44 | + |
| 45 | +```rust |
| 46 | +use std::any::Any; |
| 47 | + |
| 48 | +trait MyAny: Any {} |
| 49 | + |
| 50 | +impl dyn MyAny { |
| 51 | + fn downcast_ref<T>(&self) -> Option<&T> { |
| 52 | + (self as &dyn Any).downcast_ref() |
| 53 | + } |
| 54 | +} |
| 55 | +``` |
| 56 | + |
| 57 | +You can [learn more about trait upcasting in the Rust reference](https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions). |
| 58 | + |
| 59 | +### `HashMap`s and slices now support indexing multiple elements mutably |
| 60 | + |
| 61 | +The borrow checker will prevent simaltaneous usage of references returned from `get_mut` methods. To get around this the standard library now provides a `get_disjoint_mut` helper on slices and `HashMap` to retrieve mutable references to multiple elements simaltaneously. See the following example taken from the API docs of [`slice::get_disjoint_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_disjoint_mut): |
| 62 | +```rust |
| 63 | +let v = &mut [1, 2, 3]; |
| 64 | +if let Ok([a, b]) = v.get_disjoint_mut([0, 2]) { |
| 65 | + *a = 413; |
| 66 | + *b = 612; |
| 67 | +} |
| 68 | +assert_eq!(v, &[413, 2, 612]); |
| 69 | + |
| 70 | +if let Ok([a, b]) = v.get_disjoint_mut([0..1, 1..3]) { |
| 71 | + a[0] = 8; |
| 72 | + b[0] = 88; |
| 73 | + b[1] = 888; |
| 74 | +} |
| 75 | +assert_eq!(v, &[8, 88, 888]); |
| 76 | + |
| 77 | +if let Ok([a, b]) = v.get_disjoint_mut([1..=2, 0..=0]) { |
| 78 | + a[0] = 11; |
| 79 | + a[1] = 111; |
| 80 | + b[0] = 1; |
| 81 | +} |
| 82 | +assert_eq!(v, &[1, 11, 111]); |
| 83 | +``` |
| 84 | + |
| 85 | +### Allow safe functions to be marked with the #[target_feature] attribute. |
| 86 | + |
| 87 | +Functions marked with `#[target_feature]` are generally considered as unsafe functions: they are unsafe to call, cannot *generally* be assigned to safe function pointers, and don't implement the `Fn*` traits. |
| 88 | + |
| 89 | +However, calling them from other `#[target_feature]` functions with a superset of features is safe. |
| 90 | + |
| 91 | +```rust |
| 92 | +// Demonstration function |
| 93 | +#[target_feature(enable = "avx2")] |
| 94 | +fn avx2() {} |
| 95 | + |
| 96 | +fn foo() { |
| 97 | + // Calling `avx2` here is unsafe, as we must ensure |
| 98 | + // that AVX is available first. |
| 99 | + unsafe { |
| 100 | + avx2(); |
| 101 | + } |
| 102 | +} |
| 103 | + |
| 104 | +#[target_feature(enable = "avx2")] |
| 105 | +fn bar() { |
| 106 | + // Calling `avx2` here is safe. |
| 107 | + avx2(); |
| 108 | +} |
| 109 | +``` |
| 110 | + |
| 111 | +### Debug assert pointers are non-null when required for soundness |
| 112 | + |
| 113 | +The compiler will now insert checks 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: |
| 114 | +```rust |
| 115 | +let _x = *std::ptr::null::<u8>(); |
| 116 | +let _x = &*std::ptr::null::<u8>(); |
| 117 | +``` |
| 118 | +Trivial examples like this have produced a warning since Rust 1.53.0, the new runtime check will detect these scenarios regardless of complexity. |
| 119 | + |
| 120 | +### Make `missing_abi` lint warn by default |
| 121 | + |
| 122 | +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`). |
| 123 | + |
| 124 | +### Target deprecation warning for 1.87.0 |
| 125 | + |
| 126 | +The target `i586-pc-windows-msvc` will be removed in the next version of Rust, 1.87.0. This is because this target is effectively useless. 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, so this target does not fulfill a purpose. |
| 127 | + |
| 128 | +You can check the [Major Change Proposal](https://github.com/rust-lang/compiler-team/issues/840) for more information. |
| 129 | + |
| 130 | +### Stabilized APIs |
| 131 | + |
| 132 | +- [`{float}::next_down`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.next_down) |
| 133 | +- [`{float}::next_up`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.next_up) |
| 134 | +- [`HashMap::get_disjoint_mut`](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.get_disjoint_mut) |
| 135 | +- [`HashMap::get_disjoint_unchecked_mut`](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.get_disjoint_unchecked_mut) |
| 136 | +- [`NonZero::count_ones`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.count_ones) |
| 137 | +- [`Vec::pop_if`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.pop_if) |
| 138 | +- [`sync::Once::wait`](https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.wait) |
| 139 | +- [`sync::Once::wait_force`](https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.wait_force) |
| 140 | +- [`sync::OnceLock::wait`](https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html#method.wait) |
| 141 | +- [`<[_]>::get_disjoint_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_disjoint_mut) |
| 142 | +- [`<[_]>::get_disjoint_unchecked_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_disjoint_unchecked_mut) |
| 143 | +- [`slice::GetDisjointMutError`](https://doc.rust-lang.org/stable/std/slice/enum.GetDisjointMutError.html) |
| 144 | + |
| 145 | + |
| 146 | +These APIs are now stable in const contexts: |
| 147 | + |
| 148 | +- [`io::Cursor::get_mut`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.get_mut) |
| 149 | +- [`io::Cursor::set_position`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.set_position) |
| 150 | +- [`str::is_char_boundary`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.is_char_boundary) |
| 151 | +- [`str::split_at`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at) |
| 152 | +- [`str::split_at_checked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_checked) |
| 153 | +- [`str::split_at_mut`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_mut) |
| 154 | +- [`str::split_at_mut_checked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_mut_checked) |
| 155 | +- [`hint::black_box`](https://doc.rust-lang.org/stable/std/hint/fn.black_box.html) |
| 156 | + |
| 157 | +### Other changes |
| 158 | + |
| 159 | +Check out everything that changed in [Rust](https://github.com/rust-lang/rust/releases/tag/1.86.0), [Cargo](https://doc.rust-lang.org/nightly/cargo/CHANGELOG.html#cargo-186-2025-04-03), and [Clippy](https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-186). |
| 160 | + |
| 161 | +## Contributors to 1.86.0 |
| 162 | + |
| 163 | +Many people came together to create Rust 1.86.0. We couldn't have done it without all of you. [Thanks!](https://thanks.rust-lang.org/rust/1.86.0/) |
0 commit comments