|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "Announcing Rust 1.65.0" |
| 4 | +author: The Rust Release Team |
| 5 | +release: true |
| 6 | +--- |
| 7 | + |
| 8 | +The Rust team is happy to announce a new version of Rust, 1.65.0. Rust is a |
| 9 | +programming language empowering everyone to build reliable and efficient |
| 10 | +software. |
| 11 | + |
| 12 | +--- |
| 13 | + |
| 14 | +Before going into the details of the new Rust release, we'd like to draw |
| 15 | +attention to the tragic [death of Mahsa |
| 16 | +Amini](https://en.wikipedia.org/wiki/Death_of_Mahsa_Amini) and the death and |
| 17 | +violent suppression of many others, by the religious morality police of Iran. |
| 18 | +See <https://en.wikipedia.org/wiki/Mahsa_Amini_protests> for more details. We |
| 19 | +stand in solidarity with the people in Iran struggling for human rights. |
| 20 | + |
| 21 | +--- |
| 22 | + |
| 23 | +If you have a previous version of Rust installed via rustup, you can get 1.65.0 |
| 24 | +with: |
| 25 | + |
| 26 | +```console |
| 27 | +rustup update stable |
| 28 | +``` |
| 29 | + |
| 30 | +If you don't have it already, you can [get |
| 31 | +`rustup`](https://www.rust-lang.org/install.html) from the appropriate page on |
| 32 | +our website, and check out the [detailed release notes for |
| 33 | +1.65.0](https://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-1650-2022-11-03) |
| 34 | +on GitHub. |
| 35 | + |
| 36 | +If you'd like to help us out by testing future releases, you might consider |
| 37 | +updating locally to use the beta channel (`rustup default beta`) or the nightly |
| 38 | +channel (`rustup default nightly`). Please |
| 39 | +[report](https://github.com/rust-lang/rust/issues/new/choose) any bugs you |
| 40 | +might come across! |
| 41 | + |
| 42 | +## What's in 1.65.0 stable |
| 43 | + |
| 44 | +### Generic associated types (GATs) |
| 45 | + |
| 46 | +Lifetime, type, and const generics can now be defined on associated types, like so: |
| 47 | + |
| 48 | +```rust |
| 49 | +trait Foo { |
| 50 | + type Bar<'x>; |
| 51 | +} |
| 52 | +``` |
| 53 | + |
| 54 | +It's hard to put into few words just how useful these can be, so here are a |
| 55 | +few example traits, to get a sense of their power: |
| 56 | + |
| 57 | +```rust |
| 58 | +/// An `Iterator`-like trait that can borrow from `Self` |
| 59 | +trait LendingIterator { |
| 60 | + type Item<'a> where Self: 'a; |
| 61 | + |
| 62 | + fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>; |
| 63 | +} |
| 64 | + |
| 65 | +/// Can be implemented over smart pointers, like `Rc` or `Arc`, |
| 66 | +/// in order to allow being generic over the pointer type |
| 67 | +trait PointerFamily { |
| 68 | + type Pointer<T>: Deref<Target = T>; |
| 69 | + |
| 70 | + fn new<T>(value: T) -> Self::Pointer<T>; |
| 71 | +} |
| 72 | + |
| 73 | +/// Allows borrowing an array of items. Useful for |
| 74 | +/// `NdArray`-like types that don't necessarily store |
| 75 | +/// data contiguously. |
| 76 | +trait BorrowArray<T> { |
| 77 | + type Array<'x, const N: usize> where Self: 'x; |
| 78 | + |
| 79 | + fn borrow_array<'a, const N: usize>(&'a self) -> Self::Array<'a, N>; |
| 80 | +} |
| 81 | +``` |
| 82 | + |
| 83 | +As you can see, GATs are quite versatile and enable a number |
| 84 | +of patterns that are not currently able to be written. For more |
| 85 | +information, check out the post announcing the |
| 86 | +[push for stabilization](https://blog.rust-lang.org/2021/08/03/GATs-stabilization-push.html) |
| 87 | +published last year or the |
| 88 | +[stabilization announcement post](https://blog.rust-lang.org/2022/10/28/gats-stabilization.html) |
| 89 | +published last week. The former goes into a bit more depth |
| 90 | +of a couple of the examples above, while the latter talks |
| 91 | +about some of the known limitations of this stabilization. |
| 92 | + |
| 93 | +More in depth reading can be found in the associated types |
| 94 | +section of the [nightly reference](https://doc.rust-lang.org/nightly/reference/items/associated-items.html#associated-types) |
| 95 | +or the [original RFC](https://rust-lang.github.io/rfcs/1598-generic_associated_types.html) (which was initially opened over 6.5 years ago!). |
| 96 | + |
| 97 | +### `let`-`else` statements |
| 98 | + |
| 99 | +This introduces a new type of `let` statement with a refutable pattern and a |
| 100 | +diverging `else` block that executes when that pattern doesn't match. |
| 101 | + |
| 102 | + let PATTERN: TYPE = EXPRESSION else { |
| 103 | + DIVERGING_CODE; |
| 104 | + }; |
| 105 | + |
| 106 | +Normal `let` statements can only use _irrefutable_ patterns, statically known |
| 107 | +to always match. That pattern is often just a single variable binding, but may |
| 108 | +also unpack compound types like structs, tuples, and arrays. However, that was |
| 109 | +not usable for conditional matches, like pulling out a variant of an enum -- |
| 110 | +until now! With `let`-`else`, a refutable pattern can match and bind variables |
| 111 | +in the surrounding scope like a normal `let`, or else diverge (e.g. `break`, |
| 112 | +`return`, `panic!`) when the pattern doesn't match. |
| 113 | + |
| 114 | +```rust |
| 115 | +fn get_count_item(s: &str) -> (u64, &str) { |
| 116 | + let mut it = s.split(' '); |
| 117 | + let (Some(count_str), Some(item)) = (it.next(), it.next()) else { |
| 118 | + panic!("Can't segment count item pair: '{s}'"); |
| 119 | + }; |
| 120 | + let Ok(count) = u64::from_str(count_str) else { |
| 121 | + panic!("Can't parse integer: '{count_str}'"); |
| 122 | + }; |
| 123 | + (count, item) |
| 124 | +} |
| 125 | +assert_eq!(get_count_item("3 chairs"), (3, "chairs")); |
| 126 | +``` |
| 127 | + |
| 128 | +The scope of name bindings is the main thing that makes this different from |
| 129 | +`match` or `if let`-`else` expressions. You could previously approximate these |
| 130 | +patterns with an unfortunate bit of repetition and an outer `let`: |
| 131 | + |
| 132 | +```rust |
| 133 | + let (count_str, item) = match (it.next(), it.next()) { |
| 134 | + (Some(count_str), Some(item)) => (count_str, item), |
| 135 | + _ => panic!("Can't segment count item pair: '{s}'"), |
| 136 | + }; |
| 137 | + let count = if let Ok(count) = u64::from_str(count_str) { |
| 138 | + count |
| 139 | + } else { |
| 140 | + panic!("Can't parse integer: '{count_str}'"); |
| 141 | + }; |
| 142 | +``` |
| 143 | + |
| 144 | +### `break` from labeled blocks |
| 145 | + |
| 146 | +Plain block expressions can now be labeled as a `break` target, terminating |
| 147 | +that block early. This may sound a little like a `goto` statement, but it's not |
| 148 | +an arbitrary jump, only from within a block to its end. This was already |
| 149 | +possible with `loop` blocks, and you may have seen people write loops that |
| 150 | +always execute only once, just to get a labeled `break`. |
| 151 | + |
| 152 | +Now there's a language feature specifically for that! Labeled `break` may also |
| 153 | +include an expression value, just as with loops, letting a multi-statement |
| 154 | +block have an early "return" value. |
| 155 | + |
| 156 | +```rust |
| 157 | +let result = 'block: { |
| 158 | + do_thing(); |
| 159 | + if condition_not_met() { |
| 160 | + break 'block 1; |
| 161 | + } |
| 162 | + do_next_thing(); |
| 163 | + if condition_not_met() { |
| 164 | + break 'block 2; |
| 165 | + } |
| 166 | + do_last_thing(); |
| 167 | + 3 |
| 168 | +}; |
| 169 | +``` |
| 170 | + |
| 171 | +### Splitting Linux debuginfo |
| 172 | + |
| 173 | +Back in Rust 1.51, the compiler team added support for [split debug |
| 174 | +information](https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#splitting-debug-information) |
| 175 | +on macOS, and now this option is stable for use on Linux as well. |
| 176 | + |
| 177 | +- `-Csplit-debuginfo=unpacked` will split debuginfo out into multiple `.dwo` |
| 178 | + DWARF object files. |
| 179 | +- `-Csplit-debuginfo=packed` will produce a single `.dwp` DWARF package |
| 180 | + alongside your output binary with all the debuginfo packaged together. |
| 181 | +- `-Csplit-debuginfo=off` is still the default behavior, which includes DWARF |
| 182 | + data in `.debug_*` ELF sections of the objects and final binary. |
| 183 | + |
| 184 | +Split DWARF lets the linker avoid processing the debuginfo (because it isn't in |
| 185 | +the object files being linked anymore), which can speed up link times! |
| 186 | + |
| 187 | +Other targets now also accept `-Csplit-debuginfo` as a stable option with their |
| 188 | +platform-specific default value, but specifying other values is still unstable. |
| 189 | + |
| 190 | +### Stabilized APIs |
| 191 | + |
| 192 | +The following methods and trait implementations are now stabilized: |
| 193 | + |
| 194 | +- [`std::backtrace::Backtrace`](https://doc.rust-lang.org/stable/std/backtrace/struct.Backtrace.html) |
| 195 | +- [`Bound::as_ref`](https://doc.rust-lang.org/stable/std/ops/enum.Bound.html#method.as_ref) |
| 196 | +- [`std::io::read_to_string`](https://doc.rust-lang.org/stable/std/io/fn.read_to_string.html) |
| 197 | +- [`<*const T>::cast_mut`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.cast_mut) |
| 198 | +- [`<*mut T>::cast_const`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.cast_const) |
| 199 | + |
| 200 | +Of particular note, the `Backtrace` API allows capturing a stack backtrace at |
| 201 | +any time, using the same platform-specific implementation that usually serves |
| 202 | +panic backtraces. This may be useful for adding runtime context to error types, |
| 203 | +for example. |
| 204 | + |
| 205 | +These APIs are now usable in const contexts: |
| 206 | + |
| 207 | +- [`<*const T>::offset_from`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from) |
| 208 | +- [`<*mut T>::offset_from`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from) |
| 209 | + |
| 210 | +### Compatibility notes |
| 211 | + |
| 212 | +- As the final step of the [RLS |
| 213 | + deprecation](https://blog.rust-lang.org/2022/07/01/RLS-deprecation.html), |
| 214 | + this release has replaced RLS with a small LSP server showing a deprecation |
| 215 | + warning, advising users to migrate to `rust-analyzer`. |
| 216 | + |
| 217 | +### Other changes |
| 218 | + |
| 219 | +There are other changes in the Rust 1.65 release, including: |
| 220 | + |
| 221 | +- MIR inlining is now enabled for optimized compilations. This provides a 3-10% |
| 222 | + improvement in compiletimes for real world crates. |
| 223 | +- When scheduling builds, Cargo now sorts the queue of pending jobs to improve performance. |
| 224 | + |
| 225 | +Check out everything that changed in |
| 226 | +[Rust](https://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-1650-2022-11-03), |
| 227 | +[Cargo](https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-165-2022-11-03), |
| 228 | +and [Clippy](https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-165). |
| 229 | + |
| 230 | +### Contributors to 1.65.0 |
| 231 | + |
| 232 | +Many people came together to create Rust 1.65.0. |
| 233 | +We couldn't have done it without all of you. |
| 234 | +[Thanks!](https://thanks.rust-lang.org/rust/1.65.0/) |
0 commit comments