Series: The Rust Annals
Vol. I Issue 62 nlopes.dev
Announcing Rust 1.61.0
Rust 1.61 makes command-line exit behavior customizable through stable termination types, expands what const fn may express, and removes an unnecessary lifetime restriction from locked standard I/O handles. It also makes several pointer and slice operations usable in const contexts, while signaling possible future increases to Linux and glibc baseline requirements.
Main functions can return custom exit codes
Originally, Rust main functions could return only (), which always indicated success; another status required calling process::exit(code). Since Rust 1.26, main has also accepted a Result: Ok maps to C EXIT_SUCCESS, while Err maps to EXIT_FAILURE and debug-prints the error.
Rust 1.61 stabilizes the Termination trait that unifies these return types, together with ExitCode, which wraps platform-specific return types. ExitCode provides SUCCESS and FAILURE constants and implements From<u8> for other values. Programs may implement Termination for their own types to perform custom reporting before producing an ExitCode.
The release post demonstrates a type-safe return type for a git bisect run script:
use std::process::{ExitCode, Termination};
#[repr(u8)]
pub enum GitBisectResult {
Good = 0,
Bad = 1,
Skip = 125,
Abort = 255,
}
impl Termination for GitBisectResult {
fn report(self) -> ExitCode {
// Maybe print a message here
ExitCode::from(self as u8)
}
}
fn main() -> GitBisectResult {
std::panic::catch_unwind(|| {
todo!("test the commit")
}).unwrap_or(GitBisectResult::Abort)
}
Const functions accept more kinds of signatures and values
Several incremental stabilizations broaden what can be expressed in const fn:
- Function pointers may be created, passed, and cast. This could be useful for building compile-time function tables for an interpreter, but calling function pointers is still not permitted.
- Generic parameters may have trait bounds such as
T: Copy; previously onlySizedwas allowed. const fnmay deal withdyn Traittrait objects.- Arguments and return values may use opaque
impl Traittypes.
The trait-related features do not yet permit calls to those traits' methods inside a const fn. The Constant Evaluation reference describes current const-context capabilities, while future work is tracked in rust#57563.
Locked standard I/O handles no longer borrow temporary handles
Stdin, Stdout, and Stderr each provide lock(&self) for more control over synchronizing reads and writes. Their guards previously borrowed &self, limiting each guard to the original handle's scope. Because the underlying locks are actually stored statically, Rust 1.61 returns guards with a 'static lifetime, disconnected from the handle.
Consequently, the following one-statement pattern now works instead of producing the shown temporary-borrow error:
// error[E0716]: temporary value dropped while borrowed
let out = std::io::stdout().lock();
// ^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
// |
// creates a temporary which is freed while still in use
Standard-library stabilization extends into const pointer operations
Alongside the extracted stable API inventory, Rust 1.61 stabilizes the Write implementation for Cursor<[u8; N]>.
The release also makes the following previously stable mutable-pointer operations usable in const contexts:
<*mut T>::offset<*mut T>::wrapping_offset<*mut T>::add<*mut T>::sub<*mut T>::wrapping_add<*mut T>::wrapping_sub
Higher Linux and glibc baselines are being considered
The project plans in a future release to increase the Linux kernel baseline to version 3.2 and the glibc baseline to version 2.17. This is not the current Rust 1.61 baseline; feedback was requested in rust#95026.