Series: The Rust Annals
Vol. I Issue 60 nlopes.dev
Announcing Rust 1.59.0
Inline assembly, destructuring assignment, and more flexible const generics make this a substantial language release.
Rust 1.59 stabilizes inline assembly for four architecture families, adds destructuring assignment and more flexible const-generic declarations, and gives Cargo tools for finding future incompatibilities and stripping linked binaries. Incremental compilation is temporarily disabled by default on stable to mitigate a compiler bug that can cause deserialization errors and panics.
Inline assembly provides target-specific machine control
The Rust language now supports inline assembly, enabling applications that need very low-level control over execution or access to specialized machine instructions. The stable asm! and global_asm! macros use the same format-string syntax for naming registers as Rust format strings.
On x86-64, for example:
use std::arch::asm;
// Multiply x by 6 using shifts and adds
let mut x: u64 = 4;
unsafe {
asm!(
"mov {tmp}, {x}",
"shl {tmp}, 1",
"shl {x}, 2",
"add {x}, {tmp}",
x = inout(reg) x,
tmp = out(reg) _,
);
}
assert_eq!(x, 4 * 6);
The available assembly language and instructions depend on the target architecture. Stable Rust currently supports inline assembly on:
- x86 and x86-64
- ARM
- AArch64
- RISC-V
Further examples appear in Rust By Example, with detailed syntax in the reference.
Assignments and const generics gain more flexible forms
Tuple, slice, and struct patterns can now appear on the left-hand side of an assignment, making assignment more consistent with let bindings:
let (a, b, c, d, e);
(a, b) = (1, 2);
[c, .., d, _] = [1, 2, 3, 4, 5];
Struct { e, .. } = Struct { e: 5, f: 3 };
assert_eq!([1, 2, 1, 4, 5], [a, b, c, d, e]);
Destructuring assignments cannot use operators such as +=.
Generic types can now give const parameters default values:
struct ArrayStorage<T, const N: usize = 2> {
arr: [T; N],
}
impl<T> ArrayStorage<T> {
fn new(a: T, b: T) -> ArrayStorage<T> {
ArrayStorage {
arr: [a, b],
}
}
}
Type parameters previously had to precede every const parameter. That restriction is relaxed, so type and const parameters may now be interleaved:
fn cartesian_product<
T, const N: usize,
U, const M: usize,
V, F
>(a: [T; N], b: [U; M], f: F) -> [[V; N]; M]
where
F: FnMut(&T, &U) -> V
{
// ...
}
Cargo exposes future breakage and strips binaries during linking
Compiler bugs sometimes permit code that should have been rejected; one example was borrowing packed-struct fields in safe code. Such code in a dependency might otherwise go unnoticed until a later compiler rejects it.
After cargo build or cargo check, Cargo now warns when a dependency contains code that a future Rust version will reject:
warning: the following packages contain code that will be rejected by a future version of Rust: old_dep v0.1.0
note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`
The command named in the warning produces a full report, giving users time to upgrade the affected dependency before it breaks the build.
Cargo and rustc can also strip unnecessary information while a binary is linked, instead of requiring a separate manual step:
[profile.release]
strip = "debuginfo"
This release-profile setting removes debuginfo. The value "symbols", or simply true, removes all symbol information where supported. The standard library typically includes debug symbols and line-level debuginfo even when the surrounding Rust binary is built without debug symbols; the stripping option can remove that information and produce a smaller binary. See the Cargo documentation for details.
Stable temporarily disables incremental compilation and expands the library
Rust 1.59 disables incremental compilation by default on the stable channel to mitigate compiler bug #94124, which can cause deserialization errors and panics while compiling with incremental compilation enabled. It can still be requested explicitly with RUSTC_FORCE_INCREMENTAL=1.
The specific fix is already in the 1.60 beta, which is due to ship in six weeks. The team was not aware of other issues that would favor keeping incremental compilation disabled in Rust 1.60 stable; if none arise, it is likely to be enabled there again. Incremental compilation remains enabled by default on beta and nightly. Users are encouraged to test those channels and report problems, particularly because reports help the team judge incremental breakage and how many users it affects.
The stabilized library inventory also includes ARMv8 NEON intrinsics for AArch64. char::TryFromCharError now implements Clone, Debug, Display, PartialEq, Copy, Eq, and Error.
Four previously stable functions are now usable in const contexts:
mem::MaybeUninit::as_ptrmem::MaybeUninit::assume_initmem::MaybeUninit::assume_init_refffi::CStr::from_bytes_with_nul_unchecked