Series: The Rust Annals
Vol. I Issue 80 nlopes.dev
Announcing Rust 1.79.0
Two substantial language additions, broader temporary lifetime extension, and extensive library stabilization make this a notable release.
Rust 1.79 makes const expressions easier to use inline and with generics, permits bounds directly on associated types within other bounds, and extends temporary lifetimes in more control-flow expressions. It also builds the distributed standard library with frame pointers to make downstream profiling easier and stabilizes a broad set of library and const APIs.
Inline const blocks remove auxiliary declarations
const { ... } blocks are now stable in expression position. They explicitly enter a const context without requiring a separate const item or an associated constant on a trait.
Unlike const items, inline consts can use in-scope generics and have their type inferred. An array previously written with a separate declaration:
const EMPTY: Option<Vec<u8>> = None;
let foo = [EMPTY; 100];can now be written inline:
let foo = [const { None }; 100];The same facility works in generic contexts, avoiding the verbose trait and associated-constant machinery that was previously required:
fn create_none_array<T, const N: usize>() -> [Option<T>; N] {
[const { None::<T> }; N]
}This makes such code more succinct and easier to read. The reference documentation has further details.
Associated types can carry bounds where they are named
Associated item bounds syntax is now stable, allowing bounds in associated type position within another bound: T: Trait<Assoc: Bounds...>. This avoids introducing an extra explicit generic type solely to constrain the associated type.
- In
whereclauses,where T: Trait<Assoc: Bound>is equivalent towhere T: Trait, <T as Trait>::Assoc: Bound. - In supertraits, a bound written with the new syntax is implied when the trait is used, unlike a
whereclause:trait CopyIterator: Iterator<Item: Copy> {}. - Associated type item bounds can constrain nested rigid projections associated with a trait’s associated types:
trait Trait { type Assoc: Trait2<Assoc2: Copy>; }. - Opaque type bounds for RPIT and TAIT can constrain an associated type without naming the opaque type. For example,
impl Iterator<Item: Copy>defines an iterator whose item isCopywithout naming that item type.
See the stabilization report for more detail.
Referenced temporaries live long enough across if and match expressions
Temporaries immediately referenced during construction now receive automatic lifetime extension in if and match constructs, matching the existing behavior of block constructs.
let a = if true {
..;
&temp() // used to error, but now gets lifetime extended
} else {
..;
&temp() // used to error, but now gets lifetime extended
};let a = match () {
_ => {
..;
&temp() // used to error, but now gets lifetime extended
}
};These forms are now consistent with the prior block behavior:
let a = {
..;
&temp() // lifetime is extended
};The change is backwards compatible because the newly accepted programs previously failed to compile.
Frame pointers improve profiling of the distributed standard library
The standard library distributed by the Rust project is now compiled with -Cforce-frame-pointers=yes, making it easier for downstream users to profile their programs. The standard library continues to include line-level debug information such as DWARF, although that information is stripped by default in Cargo release profiles.
Library stabilization spans unsafe operations, pointers, text, paths, macros, and const I/O
The stabilized inventory contains 22 newly stable APIs, including unchecked integer arithmetic, unchecked slice splitting, UTF-8 chunk iteration, pointer alignment and slice-metadata queries, C-string byte counting, I/O error downcasting, the generic nonzero integer type, absolute-path construction, and byte-character and C-string procedural-macro literals.
The final 11 entries in the inventory are existing APIs newly stable in const contexts: atomic extraction; cursor construction, access, and position; empty, repeating, and sink I/O constructors; and caller-location accessors.