This is an English version of my blog post. The original version (in Japanese) is here.
Rust releases a new version every 6 weeks.
Throughout 2025, versions 1.84.0 through 1.92.0 were released. Each release includes a wide range of improvements — reading the release notes makes it clear how steadily Rust is evolving.
In this post, I’ll highlight updates relevant to low-level systems development.
Naked functions
In Rust 1.88.0, naked functions were stabilized. Normally, Rust inserts special prologue and epilogue code at function entry and exit. This can cause problems when you use inline assembly and return directly to the caller in your assembly code, because it skips the epilogue code necessary for proper function return. For example, if certain registers are pushed onto the stack in the prologue and are supposed to be popped in the epilogue, skipping these steps can leave the stack pointer in an incorrect state. The Rust compiler won’t add this special prologue and epilogue code to functions with the naked attribute, allowing you to handle the return sequence from inline assembly manually.
https://blog.rust-lang.org/2025/06/26/Rust-1.88.0/#naked-functions
In the official blog post, the example adds #[unsafe(naked)] attribute to the function. You may not be familiar with unsafe in attributes, but this feature was introduced in the Rust 2024 edition.
https://doc.rust-lang.org/edition-guide/rust-2024/unsafe-attributes.html
Improvements to raw pointer handling
In low-level systems development, raw pointers are often unavoidable. Raw pointers are challenging because using them bypasses Rust’s ownership and lifetime models, which are the language’s key safety features.
One of the big changes is strict provenance APIs introduced in 1.84.0.
Announcing Rust 1.84.0 | Rust Blog
With these APIs, the compiler can understand where raw pointers originate, which provides benefits when using tools like Miri and CHERI.
In 1.84.0, creating pointers from pointer dereferences became safe (e.g., addr_of!((*ptr).field) — this code only generates an address, so it's safe even if ptr is invalid). Additionally, a lint was added that warns when creating pointers from immediately-dropped values.
- Taking a raw ref (
&raw (const|mut)) of a deref of pointer (*ptr) is always safe by compiler-errors · Pull Request #129248 · rust-lang/rust - Lint against getting pointers from immediately dropped temporaries by GrigorenkoPV · Pull Request #128985 · rust-lang/rust
1.86.0 added debug assertions to check whether accessed raw pointers are non-null. This makes invalid pointer access cause a runtime panic when debug assertions are enabled in the build.
Announcing Rust 1.86.0 | Rust Blog
Overall, Rust has added more safety checks and tooling support around raw pointer usage.
Edition 2024
One of the biggest changes in 2025 is that Rust Edition 2024 was released. Edition 2024 is available from 1.85.0. You can see the details in the Edition Guide.
The following changes are particularly relevant to low-level systems programming:
-
unsafe extern
- The unsafe keyword can be applied to an extern block (e.g., when calling external C functions), allowing the potential unsafety to be expressed more explicitly.
-
unsafe attribute
- Attributes that require developers to uphold the required safety guarantees, such as no_mangle and extern_name, now require the unsafe keyword.
-
unsafe_op_in_unsafe_fn warning
- A lint that warns when calling unsafe functions inside unsafe functions without wrapping them in an unsafe block is now enabled by default
-
Disallow references to static mut
- A lint that makes references to static mut variables a compilation error is now enabled by default
These changes require unsafe annotations in more places, and the lints have become stricter.
Target features
In 1.86.0, the #[target_feature] attribute can now be applied to safe functions. Normally, calling functions marked with target_feature requires an unsafe block, but when calling them from a function with the same target feature enabled, no unsafe annotation is needed.
Announcing Rust 1.86.0 | Rust Blog
In 1.87.0, unsafe functions in std::arch were converted to safe functions using this target feature mechanism, and in 1.89.0, even more functions became safe.
asm goto
You can now jump from inline assembly to code blocks written in Rust.
Announcing Rust 1.87.0 and ten years of Rust! | Rust Blog
Here is the example from the document:
unsafe {
core::arch::asm!(“jmp {}”, label {
println!(“Hello from inline assembly label”);
});
}
Other notable changes
There were many more changes. Here is the list:
- drop will be executed in unwinding when extern “C” function panics(1.84.0)
- A lint that warns when ABI is omitted in extern is now enabled by default (1.86.0)
- Cross-compiled doctests are supported (1.89.0)
- i128 and u128 are now allowed in extern “C” functions (1.89.0)
- The compiler can infer arguments to const generics (1.89.0)
Conclusion
There were several changes in Rust, although this post focused on low-level systems development.
These updates will help us write safer low-level systems code in Rust.
Top comments (0)