Series: The Rust Annals
Vol. I Issue 93 nlopes.dev
Announcing Rust 1.92.0
Rust 1.92 advances preparation for never type stabilization by making two future-compatibility lints deny-by-default, while avoiding unnecessary unused_must_use warnings for results that cannot fail. It also restores backtraces by default for Linux programs built with -Cpanic=abort, tightens validation of #[macro_export], and stabilizes allocation, synchronization, collection, procedural-macro, and const slice APIs.
Never type compatibility problems now cause direct-build errors
The never type stabilization work advances by making the never_type_fallback_flowing_into_unsafe and dependency_on_unit_never_type_fallback future-compatibility lints deny-by-default. When detected, they now cause a compilation error.
They remain lints and can be #[allow]ed. They fire only when an affected crate is built directly; when that crate is built as a dependency, Cargo reports a warning instead. The checks identify code likely to be broken by never type stabilization, so affected crates are highly advised to fix them.
The language team estimates that approximately 500 crates are affected. It considers this acceptable because lints are not a breaking change and the change will allow future stabilization of the never type; its fuller justification appears in the Language Team’s assessment.
Infallible results no longer trigger unused_must_use
The unused_must_use lint normally warns when code ignores a function result whose function or return type has #[must_use], including a Result that might need ? or .expect("..."). Rust 1.92 no longer warns for Result<(), UninhabitedType> or ControlFlow<UninhabitedType, ()>, where the error or break type has no constructible values, such as ! or Infallible. This avoids requiring a check for an error that can never happen.
use core::convert::Infallible;
fn can_never_fail() -> Result<(), Infallible> {
// ...
Ok(())
}
fn main() {
can_never_fail();
}
This also handles traits whose associated error type is infallible in some implementations but not others:
trait UsesAssocErrorType {
type Error;
fn method(&self) -> Result<(), Self::Error>;
}
struct CannotFail;
impl UsesAssocErrorType for CannotFail {
type Error = core::convert::Infallible;
fn method(&self) -> Result<(), Self::Error> {
Ok(())
}
}
struct CanFail;
impl UsesAssocErrorType for CanFail {
type Error = std::io::Error;
fn method(&self) -> Result<(), Self::Error> {
Err(std::io::Error::other("something went wrong"))
}
}
fn main() {
CannotFail.method(); // No warning
CanFail.method(); // Warning: unused `Result` that must be used
}
Linux panic-abort builds regain backtraces by default
Backtraces with -Cpanic=abort worked in Rust 1.22 but broke in Rust 1.23 when the compiler stopped emitting unwind tables for those builds. Rust 1.45 provided -Cforce-unwind-tables=yes as a workaround.
Rust 1.92 emits unwind tables by default on Linux even when -Cpanic=abort is specified, allowing backtraces to work properly. Users who do not want unwind tables should explicitly disable them with -Cforce-unwind-tables=no.
Attribute validation and library APIs expand
Changes across recent releases to the compiler’s processing of built-in attributes should greatly improve their errors and warnings and make diagnostics more consistent across the more than 100 built-in attributes. In Rust 1.92, the compiler becomes stricter about arguments accepted by #[macro_export]: the check is now a deny-by-default lint reported in dependencies.
The stabilized API inventory includes new operations for nonzero integers, panic locations, read-write locks, zeroed allocation with Box, Rc, and Arc, B-tree map entries, and extending procedural-macro token streams. The previously stable <[_]>::rotate_left and <[_]>::rotate_right are now also stable in const contexts.