Rust 1.59 now allows developers to include machine-level instructions in Rust programs using asm!
. Additionally, destructuring has been extended beyond bindings to include assignments, and generics now support the specification of default values for const parameters.
Inline assembly support makes it possible to mix assembly-level instructions and Rust code using the new asm!
and global_asm!
macros inside of an unsafe
section.
Assembly instructions are represented through strings, e.g. "mov {tmp}, {x}"
, whereby registers names are handled using string interpolation syntax. For example, this is a minimalist example showing how you can add a NOP
instruction into the code generated by the compiler:
use std::arch::asm;
unsafe {
asm!("nop");
}
After the list of strings representing assembly instructions, the asm!
macros ends with a section specifying inputs and outputs. The following snippet shows how you can write a value read from the variable i
to input register 1, then move it to output register 0, add 5 to it, and finally write its content to output variable o
.
let i: u64 = 3;
let o: u64;
unsafe {
asm!(
"mov {0}, {1}",
"add {0}, 5",
out(reg) o,
in(reg) i,
);
}
assert_eq!(o, 8);
Rust requires developers to include inline assembly in unsafe
blocks because it could insert arbitrary code and break invariants.
The Rust compiler currently supports inline assembly for x86 and x86-64, ARM, AArch64, and RISC-V.
As mentioned, Rust 1.59 allows developers to use destructing not only in let
bindings but also in assignments. For example, you can now write:
let (part1, part2) = ("first", "second");
let (p1, p2);
(p1, p2) = ("first", "second");
Another extension to the language syntax makes it possible to specify default values for const generics and mix type parameters and const parameters in any order. For example, the following define a BitSet
generic that by default will have a size of 8:
struct BitSet<const SIZE: usize = 8>
where
[u8; (SIZE + 7) / 8]: Sized,
{
storage: [u8; (SIZE + 7) / 8],
}
On the negative side, Rust 1.59 disables incremental compilation by default due to a known bug that can cause deserialization errors. The fix will come in Rust 1.60, to be released in six weeks. So, if you are strictly dependent on incremental compilation to work, you might consider waiting for Rust 1.60 before adopting the new language features.
Rust 1.59 also stabilized a number of APIs and introduces new warnings to let developers know about a dependency that will be rejected in a future version of the language. Do not miss the official release notes to get the full detail.