Series: The Rust Annals
Vol. I Issue 59 nlopes.dev
Announcing Rust 1.58.0
Captured format arguments combine a substantial language ergonomic improvement with meaningful security and standard-library changes.
Rust 1.58 lets format strings capture identifiers from their surrounding scope, removes the current directory from the Windows Command executable search path, and completes a standard-library expansion of #[must_use]. It also stabilizes filesystem, integer, unchecked-unwrapping, and file-options APIs while making eight existing Duration functions usable in const contexts.
Format strings can capture identifiers from scope
Format strings can now capture an argument by writing {ident}. Previously, formats accepted implicit or explicit positional arguments and explicitly supplied named arguments:
println!("Hello, {}!", get_person()); // implicit position
println!("Hello, {0}!", get_person()); // explicit index
println!("Hello, {person}!", person = get_person()); // named
A named argument can now come directly from the surrounding scope:
let person = get_person();
// ...
println!("Hello, {person}!"); // captures the local `person`
Capture also works in formatting parameters:
let (width, precision) = get_format();
for (name, score) in get_scores() {
println!("{name}: {score:width$.precision$}");
}
Only plain identifiers can be captured, not arbitrary paths or expressions. More complicated arguments must first be assigned to a local name or supplied with the older name = expression form.
The feature works in every macro that accepts format strings, with one edition-specific corner case: in the 2015 and 2018 editions, panic!("{ident}") is still treated as an unformatted string, and the compiler warns that it will not have the intended effect. Following the 2021 edition’s change for improved consistency, the same form works as expected in 2021 panic!.
Windows Command searches a safer, shorter path
On Windows, std::process::Command no longer searches the parent process’s current directory for executables. The old behavior came from the Win32 CreateProcess API and could produce surprising or malicious results in untrusted directories. ripgrep, for example, published CVE-2021-3013 after discovering that its child processes could be intercepted this way; Microsoft’s PowerShell documentation likewise says it does not use the current directory for security.
Rust previously searched in this order:
- The directories in the child’s
PATH, if it was explicitly changed from the parent. - The directory from which the application loaded.
- The current directory for the parent process.
- The 32-bit Windows system directory.
- The 16-bit Windows system directory.
- The Windows directory.
- The directories in the
PATHenvironment variable.
Rust now performs the search itself, omitting both the current directory and the legacy 16-bit directory, whose location cannot be discovered through an API. The new order is:
- The directories in the child’s
PATHenvironment variable. - The directory from which the application loaded.
- The 32-bit Windows system directory.
- The Windows directory.
- The directories in the
PATHenvironment variable.
Non-Windows targets retain their platform-specific behavior, most often considering only the child or parent PATH.
The standard library catches more ignored results
The standard library’s expansion of #[must_use] is complete. The attribute marks types or functions whose value almost certainly needs explicit consideration: it has long applied to types such as Result, and it can catch code that mistakenly expects a function to mutate a value in place when the function actually returns a new value.
Library proposal 35, approved in October 2021, called for an audit and broader use of the attribute on functions whose primary effect is their return value. The idea resembles function purity but is looser than a true language feature. Some additions arrived in Rust 1.57.0; Rust 1.58.0 completes the effort.
New library APIs and const-capable Duration operations
This release stabilizes methods for symlink detection, saturating integer division, unchecked extraction from Option and Result, and constructing file-opening options. The unchecked extraction methods retain their unsafe preconditions.
Eight previously stable Duration functions are also newly usable in const contexts: construction plus checked and saturating addition, subtraction, and multiplication, together with checked division.