|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "Announcing Rust 1.58.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.58.0. |
| 9 | +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, getting Rust 1.58.0 is as easy as: |
| 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.58.0][notes] on GitHub. |
| 20 | + |
| 21 | +[install]: https://www.rust-lang.org/install.html |
| 22 | +[notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1580-2022-01-13 |
| 23 | + |
| 24 | +## What's in 1.58.0 stable |
| 25 | + |
| 26 | +Rust 1.58 brings captured identifiers in format strings, a change to the |
| 27 | +`Command` search path on Windows, more `#[must_use]` annotations in the |
| 28 | +standard library, and some new library stabilizations. |
| 29 | + |
| 30 | +### Captured identifiers in format strings |
| 31 | + |
| 32 | +Format strings can now capture arguments simply by writing `{ident}` in the |
| 33 | +string. Formats have long accepted positional arguments (optionally by index) |
| 34 | +and named arguments, for example: |
| 35 | + |
| 36 | +```rust |
| 37 | +println!("Hello, {}!", get_person()); // implicit position |
| 38 | +println!("Hello, {0}!", get_person()); // explicit index |
| 39 | +println!("Hello, {person}!", person = get_person()); // named |
| 40 | +``` |
| 41 | + |
| 42 | +Now named arguments can also be captured from the surrounding scope, like: |
| 43 | + |
| 44 | +```rust |
| 45 | +let person = get_person(); |
| 46 | +// ... |
| 47 | +println!("Hello, {person}!"); // captures the local `person` |
| 48 | +``` |
| 49 | + |
| 50 | +This may also be used in formatting parameters: |
| 51 | + |
| 52 | +```rust |
| 53 | +let (width, precision) = get_format(); |
| 54 | +for (name, score) in get_scores() { |
| 55 | + println!("{name}: {score:width$.precision$}"); |
| 56 | +} |
| 57 | +``` |
| 58 | + |
| 59 | +Format strings can only capture plain identifiers, not arbitrary paths or |
| 60 | +expressions. For more complicated arguments, either assign them to a local name |
| 61 | +first, or use the older `name = expression` style of formatting arguments. |
| 62 | + |
| 63 | +This feature works in all macros accepting format strings. However, one corner |
| 64 | +case is the `panic!` macro in 2015 and 2018 editions, where `panic!("{ident}")` |
| 65 | +is still treated as an unformatted string -- the compiler will warn about this |
| 66 | +not having the intended effect. Due to the 2021 edition's update of panic |
| 67 | +macros for [improved consistency], this works as expected in 2021 `panic!`. |
| 68 | + |
| 69 | +[improved consistency]: https://doc.rust-lang.org/stable/edition-guide/rust-2021/panic-macro-consistency.html |
| 70 | + |
| 71 | +### Reduced Windows `Command` search path |
| 72 | + |
| 73 | +On Windows targets, `std::process::Command` will no longer search the current |
| 74 | +directory for executables. That effect was owed to historical behavior of the |
| 75 | +win32 [`CreateProcess`] API, so Rust was effectively searching in this order: |
| 76 | + |
| 77 | +1. (Rust specific) The directories that are listed in the child's `PATH` |
| 78 | + environment variable, if it was explicitly changed from the parent. |
| 79 | +2. The directory from which the application loaded. |
| 80 | +3. The current directory for the parent process. |
| 81 | +4. The 32-bit Windows system directory. |
| 82 | +5. The 16-bit Windows system directory. |
| 83 | +6. The Windows directory. |
| 84 | +7. The directories that are listed in the `PATH` environment variable. |
| 85 | + |
| 86 | +However, using the current directory can lead to surprising results, or even |
| 87 | +malicious behavior when dealing with untrusted directories. For example, |
| 88 | +`ripgrep` published [CVE-2021-3013] when they learned that their child |
| 89 | +processes could be intercepted in this way. Even Microsoft's own PowerShell |
| 90 | +[documents][PS] that they do not use the current directory for security. |
| 91 | + |
| 92 | +Rust now performs its own search without the current directory, and the legacy |
| 93 | +16-bit directory is also not included, as there is no API to discover its |
| 94 | +location. So the new `Command` search order for Rust on Windows is: |
| 95 | + |
| 96 | +1. The directories that are listed in the child's `PATH` environment variable. |
| 97 | +2. The directory from which the application loaded. |
| 98 | +3. The 32-bit Windows system directory. |
| 99 | +4. The Windows directory. |
| 100 | +5. The directories that are listed in the `PATH` environment variable. |
| 101 | + |
| 102 | +Non-Windows targets continue to use their platform-specific behavior, most |
| 103 | +often only considering the child or parent `PATH` environment variable. |
| 104 | + |
| 105 | +[`CreateProcess`]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa |
| 106 | +[CVE-2021-3013]: https://www.cve.org/CVERecord?id=CVE-2021-3013 |
| 107 | +[PS]: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_command_precedence?view=powershell-7.2 |
| 108 | + |
| 109 | +### More `#[must_use]` in the standard library |
| 110 | + |
| 111 | +The `#[must_use]` attribute can be applied to types or functions when failing |
| 112 | +to explicitly consider them or their output is almost certainly a bug. This has |
| 113 | +long been used in the standard library for types like `Result`, which should be |
| 114 | +checked for error conditions. This also helps catch mistakes such as expecting |
| 115 | +a function to mutate a value in-place, when it actually returns a new value. |
| 116 | + |
| 117 | +Library [proposal 35] was approved in October 2021 to audit and expand the |
| 118 | +application of `#[must_use]` throughout the standard library, covering many |
| 119 | +more functions where the primary effect is the return value. This is similar |
| 120 | +to the idea of function purity, but looser than a true language feature. Some |
| 121 | +of these additions were present in release 1.57.0, and now in 1.58.0 the effort |
| 122 | +has completed. |
| 123 | + |
| 124 | +[proposal 35]: https://github.com/rust-lang/libs-team/issues/35 |
| 125 | + |
| 126 | +### Stabilized APIs |
| 127 | + |
| 128 | +The following methods and trait implementations were stabilized. |
| 129 | + |
| 130 | +- [`Metadata::is_symlink`] |
| 131 | +- [`Path::is_symlink`] |
| 132 | +- [`{integer}::saturating_div`] |
| 133 | +- [`Option::unwrap_unchecked`] |
| 134 | +- [`Result::unwrap_unchecked`] |
| 135 | +- [`Result::unwrap_err_unchecked`] |
| 136 | + |
| 137 | +The following previously stable functions are now `const`. |
| 138 | + |
| 139 | +- [`Duration::new`] |
| 140 | +- [`Duration::checked_add`] |
| 141 | +- [`Duration::saturating_add`] |
| 142 | +- [`Duration::checked_sub`] |
| 143 | +- [`Duration::saturating_sub`] |
| 144 | +- [`Duration::checked_mul`] |
| 145 | +- [`Duration::saturating_mul`] |
| 146 | +- [`Duration::checked_div`] |
| 147 | + |
| 148 | +[`Metadata::is_symlink`]: https://doc.rust-lang.org/stable/std/fs/struct.Metadata.html#method.is_symlink |
| 149 | +[`Path::is_symlink`]: https://doc.rust-lang.org/stable/std/path/struct.Path.html#method.is_symlink |
| 150 | +[`{integer}::saturating_div`]: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.saturating_div |
| 151 | +[`Option::unwrap_unchecked`]: https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.unwrap_unchecked |
| 152 | +[`Result::unwrap_unchecked`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.unwrap_unchecked |
| 153 | +[`Result::unwrap_err_unchecked`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.unwrap_err_unchecked |
| 154 | +[`Duration::new`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.new |
| 155 | +[`Duration::checked_add`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.checked_add |
| 156 | +[`Duration::saturating_add`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.saturating_add |
| 157 | +[`Duration::checked_sub`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.checked_sub |
| 158 | +[`Duration::saturating_sub`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.saturating_sub |
| 159 | +[`Duration::checked_mul`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.checked_mul |
| 160 | +[`Duration::saturating_mul`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.saturating_mul |
| 161 | +[`Duration::checked_div`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.checked_div |
| 162 | + |
| 163 | +### Other changes |
| 164 | + |
| 165 | +There are other changes in the Rust 1.58.0 release: check out what changed in |
| 166 | +[Rust](https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1580-2022-01-13), |
| 167 | +[Cargo](https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-158-2022-01-13), |
| 168 | +and [Clippy](https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-158). |
| 169 | + |
| 170 | +### Contributors to 1.58.0 |
| 171 | + |
| 172 | +Many people came together to create Rust 1.58.0. |
| 173 | +We couldn't have done it without all of you. |
| 174 | +[Thanks!](https://thanks.rust-lang.org/rust/1.58.0/) |
0 commit comments