|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "Announcing Rust 1.63.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.63.0. Rust is a programming language |
| 9 | +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.63.0 with: |
| 12 | + |
| 13 | +```console |
| 14 | +rustup update stable |
| 15 | +``` |
| 16 | + |
| 17 | +If you don't have it already, you can [get `rustup`][install] |
| 18 | +from the appropriate page on our website, and check out the |
| 19 | +[detailed release notes for 1.63.0][notes] on GitHub. |
| 20 | + |
| 21 | +If you'd like to help us out by testing future releases, you might consider updating locally to use |
| 22 | +the beta channel (`rustup default beta`) or the nightly channel (`rustup default nightly`). |
| 23 | +Please [report] any bugs you might come across! |
| 24 | + |
| 25 | +[install]: https://www.rust-lang.org/install.html |
| 26 | +[notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1620-2022-06-30 |
| 27 | +[report]: https://github.com/rust-lang/rust/issues/new/choose |
| 28 | + |
| 29 | +## What's in 1.63.0 stable |
| 30 | + |
| 31 | +### Scoped threads |
| 32 | + |
| 33 | +Rust code could launch new threads with `std::thread::spawn` since 1.0, but this |
| 34 | +function bounds its closure with `'static`. Roughly, this means that threads |
| 35 | +currently must have ownership of any arguments passed into their closure; you |
| 36 | +can't pass borrowed data into a thread. In cases where the threads are expected |
| 37 | +to exit by the end of the function (by being `join()`'d), this isn't strictly |
| 38 | +necessary and can require workarounds like placing the data in an [`Arc`]. |
| 39 | + |
| 40 | +Now, with 1.63.0, the standard library is adding *scoped* threads, which allow |
| 41 | +spawning a thread borrowing from the local stack frame. The |
| 42 | +[`std::thread::scope`] API provides the necessary guarantee that any spawned threads |
| 43 | +will have exited prior to itself returning, which allows for safely borrowing |
| 44 | +data. Here's an example: |
| 45 | + |
| 46 | +```rust |
| 47 | +let mut a = vec![1, 2, 3]; |
| 48 | +let mut x = 0; |
| 49 | + |
| 50 | +std::thread::scope(|s| { |
| 51 | + s.spawn(|| { |
| 52 | + println!("hello from the first scoped thread"); |
| 53 | + // We can borrow `a` here. |
| 54 | + dbg!(&a); |
| 55 | + }); |
| 56 | + s.spawn(|| { |
| 57 | + println!("hello from the second scoped thread"); |
| 58 | + // We can even mutably borrow `x` here, |
| 59 | + // because no other threads are using it. |
| 60 | + x += a[0] + a[2]; |
| 61 | + }); |
| 62 | + println!("hello from the main thread"); |
| 63 | +}); |
| 64 | + |
| 65 | +// After the scope, we can modify and access our variables again: |
| 66 | +a.push(4); |
| 67 | +assert_eq!(x, a.len()); |
| 68 | +``` |
| 69 | + |
| 70 | +[`std::thread::scope`]: https://doc.rust-lang.org/stable/std/thread/fn.scope.html |
| 71 | +[`std::thread::spawn`]: https://doc.rust-lang.org/stable/std/thread/fn.spawn.html |
| 72 | +[`Arc`]: https://doc.rust-lang.org/stable/std/sync/struct.Arc.html |
| 73 | + |
| 74 | + |
| 75 | +### Rust ownership for raw file descriptors/handles (I/O Safety) |
| 76 | + |
| 77 | +Previously, Rust code working with platform APIs taking raw file descriptors (on |
| 78 | +unix-style platforms) or handles (on Windows) would typically work directly with |
| 79 | +a platform-specific representation of the descriptor (for example, a `c_int`, or the alias `RawFd`). |
| 80 | +For Rust bindings to such native APIs, the type system then failed to encode |
| 81 | +whether the API would take ownership of the file descriptor (e.g., `close`) or |
| 82 | +merely borrow it (e.g., `dup`). |
| 83 | + |
| 84 | +Now, Rust provides wrapper types such as [`BorrowedFd`] and [`OwnedFd`], which are marked as |
| 85 | +`#[repr(transparent)]`, meaning that `extern "C"` bindings can directly take |
| 86 | +these types to encode the ownership semantics. See the stabilized APIs section |
| 87 | +for the full list of wrapper types stabilized in 1.63, currently, they are |
| 88 | +available on cfg(unix) platforms, Windows, and WASI. |
| 89 | + |
| 90 | +We recommend that new APIs use these types instead of the previous type aliases |
| 91 | +(like [`RawFd`]). |
| 92 | + |
| 93 | +[`RawFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/type.RawFd.html |
| 94 | +[`BorrowedFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/struct.BorrowedFd.html |
| 95 | +[`OwnedFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/struct.OwnedFd.html |
| 96 | + |
| 97 | +### `const` Mutex, RwLock, Condvar initialization |
| 98 | + |
| 99 | +The [`Condvar::new`], [`Mutex::new`], and [`RwLock::new`] functions are now |
| 100 | +callable in `const` contexts, which allows avoiding the use of crates like |
| 101 | +`lazy_static` for creating global statics with `Mutex`, `RwLock`, or `Condvar` |
| 102 | +values. This builds on the [work in 1.62] to enable thinner and faster mutexes |
| 103 | +on Linux. |
| 104 | + |
| 105 | +[work in 1.62]: https://blog.rust-lang.org/2022/06/30/Rust-1.62.0.html#thinner-faster-mutexes-on-linux |
| 106 | + |
| 107 | +### Turbofish for generics in functions with `impl Trait` |
| 108 | + |
| 109 | +For a function signature like `fn foo<T>(value: T, f: impl Copy)`, it was an |
| 110 | +error to specify the concrete type of `T` via turbofish: `foo::<u32>(3, 3)` |
| 111 | +would fail with: |
| 112 | + |
| 113 | +```text |
| 114 | +error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position |
| 115 | + --> src/lib.rs:4:11 |
| 116 | + | |
| 117 | +4 | foo::<u32>(3, 3); |
| 118 | + | ^^^ explicit generic argument not allowed |
| 119 | + | |
| 120 | + = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information |
| 121 | +``` |
| 122 | + |
| 123 | +In 1.63, this restriction is relaxed, and the explicit type of the generic can be specified. |
| 124 | +However, the `impl Trait` parameter, despite desugaring to a generic, remains |
| 125 | +opaque and cannot be specified via turbofish. |
| 126 | + |
| 127 | +### Non-lexical lifetimes migration complete |
| 128 | + |
| 129 | +As detailed in [this blog post], we've fully removed the previous lexical borrow checker |
| 130 | +from rustc across all editions, fully enabling the non-lexical, new, version of the borrow |
| 131 | +checker. Since the borrow checker doesn't affect the output of rustc, this won't change |
| 132 | +the behavior of any programs, but it completes a long-running migration (started in the |
| 133 | +initial stabilization of NLL for the 2018 edition) to deliver the full benefits of the new |
| 134 | +borrow checker across all editions of Rust. For most users, this change will bring |
| 135 | +slightly better diagnostics for some borrow checking errors, but will not otherwise impact |
| 136 | +which code they can write. |
| 137 | + |
| 138 | +You can read more about non-lexical lifetimes in [this section of the 2018 edition announcement][nll]. |
| 139 | + |
| 140 | +[this blog post]: https://blog.rust-lang.org/2022/08/05/nll-by-default.html |
| 141 | +[nll]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html#non-lexical-lifetimes |
| 142 | + |
| 143 | +### Stabilized APIs |
| 144 | + |
| 145 | +The following methods and trait implementations are now stabilized: |
| 146 | + |
| 147 | +- [`array::from_fn`] |
| 148 | +- [`Box::into_pin`] |
| 149 | +- [`BinaryHeap::try_reserve`] |
| 150 | +- [`BinaryHeap::try_reserve_exact`] |
| 151 | +- [`OsString::try_reserve`] |
| 152 | +- [`OsString::try_reserve_exact`] |
| 153 | +- [`PathBuf::try_reserve`] |
| 154 | +- [`PathBuf::try_reserve_exact`] |
| 155 | +- [`Path::try_exists`] |
| 156 | +- [`Ref::filter_map`] |
| 157 | +- [`RefMut::filter_map`] |
| 158 | +- [`NonNull::<[T]>::len`][`NonNull::<slice>::len`] |
| 159 | +- [`ToOwned::clone_into`] |
| 160 | +- [`Ipv6Addr::to_ipv4_mapped`] |
| 161 | +- [`unix::io::AsFd`] |
| 162 | +- [`unix::io::BorrowedFd<'fd>`] |
| 163 | +- [`unix::io::OwnedFd`] |
| 164 | +- [`windows::io::AsHandle`] |
| 165 | +- [`windows::io::BorrowedHandle<'handle>`] |
| 166 | +- [`windows::io::OwnedHandle`] |
| 167 | +- [`windows::io::HandleOrInvalid`] |
| 168 | +- [`windows::io::HandleOrNull`] |
| 169 | +- [`windows::io::InvalidHandleError`] |
| 170 | +- [`windows::io::NullHandleError`] |
| 171 | +- [`windows::io::AsSocket`] |
| 172 | +- [`windows::io::BorrowedSocket<'handle>`] |
| 173 | +- [`windows::io::OwnedSocket`] |
| 174 | +- [`thread::scope`] |
| 175 | +- [`thread::Scope`] |
| 176 | +- [`thread::ScopedJoinHandle`] |
| 177 | + |
| 178 | +These APIs are now usable in const contexts: |
| 179 | + |
| 180 | +- [`array::from_ref`] |
| 181 | +- [`slice::from_ref`] |
| 182 | +- [`intrinsics::copy`] |
| 183 | +- [`intrinsics::copy_nonoverlapping`] |
| 184 | +- [`<*const T>::copy_to`] |
| 185 | +- [`<*const T>::copy_to_nonoverlapping`] |
| 186 | +- [`<*mut T>::copy_to`] |
| 187 | +- [`<*mut T>::copy_to_nonoverlapping`] |
| 188 | +- [`<*mut T>::copy_from`] |
| 189 | +- [`<*mut T>::copy_from_nonoverlapping`] |
| 190 | +- [`str::from_utf8`] |
| 191 | +- [`Utf8Error::error_len`] |
| 192 | +- [`Utf8Error::valid_up_to`] |
| 193 | +- [`Condvar::new`] |
| 194 | +- [`Mutex::new`] |
| 195 | +- [`RwLock::new`] |
| 196 | + |
| 197 | +[`array::from_fn`]: https://doc.rust-lang.org/stable/std/array/fn.from_fn.html |
| 198 | +[`Box::into_pin`]: https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.into_pin |
| 199 | +[`BinaryHeap::try_reserve_exact`]: https://doc.rust-lang.org/stable/alloc/collections/binary_heap/struct.BinaryHeap.html#method.try_reserve_exact |
| 200 | +[`BinaryHeap::try_reserve`]: https://doc.rust-lang.org/stable/std/collections/struct.BinaryHeap.html#method.try_reserve |
| 201 | +[`OsString::try_reserve`]: https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.try_reserve |
| 202 | +[`OsString::try_reserve_exact`]: https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.try_reserve_exact |
| 203 | +[`PathBuf::try_reserve`]: https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#method.try_reserve |
| 204 | +[`PathBuf::try_reserve_exact`]: https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#method.try_reserve_exact |
| 205 | +[`Path::try_exists`]: https://doc.rust-lang.org/stable/std/path/struct.Path.html#method.try_exists |
| 206 | +[`Ref::filter_map`]: https://doc.rust-lang.org/stable/std/cell/struct.Ref.html#method.filter_map |
| 207 | +[`RefMut::filter_map`]: https://doc.rust-lang.org/stable/std/cell/struct.RefMut.html#method.filter_map |
| 208 | +[`NonNull::<slice>::len`]: https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.len |
| 209 | +[`ToOwned::clone_into`]: https://doc.rust-lang.org/stable/std/borrow/trait.ToOwned.html#method.clone_into |
| 210 | +[`Ipv6Addr::to_ipv4_mapped`]: https://doc.rust-lang.org/stable/std/net/struct.Ipv6Addr.html#method.to_ipv4_mapped |
| 211 | +[`unix::io::AsFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.AsFd.html |
| 212 | +[`unix::io::BorrowedFd<'fd>`]: https://doc.rust-lang.org/stable/std/os/unix/io/struct.BorrowedFd.html |
| 213 | +[`unix::io::OwnedFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/struct.OwnedFd.html |
| 214 | +[`windows::io::AsHandle`]: https://doc.rust-lang.org/stable/std/os/windows/io/trait.AsHandle.html |
| 215 | +[`windows::io::BorrowedHandle<'handle>`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.BorrowedHandle.html |
| 216 | +[`windows::io::OwnedHandle`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedHandle.html |
| 217 | +[`windows::io::HandleOrInvalid`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.HandleOrInvalid.html |
| 218 | +[`windows::io::HandleOrNull`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.HandleOrNull.html |
| 219 | +[`windows::io::InvalidHandleError`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.InvalidHandleError.html |
| 220 | +[`windows::io::NullHandleError`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.NullHandleError.html |
| 221 | +[`windows::io::AsSocket`]: https://doc.rust-lang.org/stable/std/os/windows/io/trait.AsSocket.html |
| 222 | +[`windows::io::BorrowedSocket<'handle>`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.BorrowedSocket.html |
| 223 | +[`windows::io::OwnedSocket`]: https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedSocket.html |
| 224 | +[`thread::scope`]: https://doc.rust-lang.org/stable/std/thread/fn.scope.html |
| 225 | +[`thread::Scope`]: https://doc.rust-lang.org/stable/std/thread/struct.Scope.html |
| 226 | +[`thread::ScopedJoinHandle`]: https://doc.rust-lang.org/stable/std/thread/struct.ScopedJoinHandle.html |
| 227 | + |
| 228 | +[`array::from_ref`]: https://doc.rust-lang.org/stable/std/array/fn.from_ref.html |
| 229 | +[`slice::from_ref`]: https://doc.rust-lang.org/stable/std/slice/fn.from_ref.html |
| 230 | +[`intrinsics::copy`]: https://doc.rust-lang.org/stable/std/intrinsics/fn.copy.html |
| 231 | +[`intrinsics::copy_nonoverlapping`]: https://doc.rust-lang.org/stable/std/intrinsics/fn.copy_nonoverlapping.html |
| 232 | +[`<*const T>::copy_to`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_to |
| 233 | +[`<*const T>::copy_to_nonoverlapping`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_to_nonoverlapping |
| 234 | +[`<*mut T>::copy_to`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_to-1 |
| 235 | +[`<*mut T>::copy_to_nonoverlapping`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_to_nonoverlapping-1 |
| 236 | +[`<*mut T>::copy_from`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_from |
| 237 | +[`<*mut T>::copy_from_nonoverlapping`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.copy_from_nonoverlapping |
| 238 | +[`str::from_utf8`]: https://doc.rust-lang.org/stable/std/str/fn.from_utf8.html |
| 239 | +[`Utf8Error::error_len`]: https://doc.rust-lang.org/stable/std/str/struct.Utf8Error.html#method.error_len |
| 240 | +[`Utf8Error::valid_up_to`]: https://doc.rust-lang.org/stable/std/str/struct.Utf8Error.html#method.valid_up_to |
| 241 | +[`Condvar::new`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.new |
| 242 | +[`Mutex::new`]: https://doc.rust-lang.org/stable/std/sync/struct.Mutex.html#method.new |
| 243 | +[`RwLock::new`]: https://doc.rust-lang.org/stable/std/sync/struct.RwLock.html#method.new |
| 244 | + |
| 245 | + |
| 246 | +### Other changes |
| 247 | + |
| 248 | +There are other changes in the Rust 1.63.0 release. Check out what changed in |
| 249 | +[Rust](https://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-1630-2022-08-11), |
| 250 | +[Cargo](https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-163-2022-08-11), |
| 251 | +and [Clippy](https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-163). |
| 252 | + |
| 253 | +### Contributors to 1.63.0 |
| 254 | + |
| 255 | +Many people came together to create Rust 1.63.0. |
| 256 | +We couldn't have done it without all of you. |
| 257 | +[Thanks!](https://thanks.rust-lang.org/rust/1.63.0/) |
0 commit comments