Rust 1.92 shipped on Thursday with async closures stabilized and, more importantly for a specific and vocal community, working under no_std. The feature had been available on nightly since late 2024, but the embedded path stayed blocked because the desugaring allocated in some cases. That is now resolved. Firmware authors can write an async closure that borrows from its environment and pass it to an executor on a Cortex-M4 without boxing, without a macro, and without the lifetime gymnastics that filled Embassy issue threads for two years. The release also stabilizes const generics for arrays in trait bounds and improves incremental compilation.
The problem async closures solve
Before this release, writing a function that accepts an async callback meant one of three unpleasant choices. You could take a closure returning a boxed future, which allocates and rules out no_std. You could define a custom trait with an associated future type and force callers to write a struct, which nobody enjoys. Or you could reach for a macro that generated the state machine, which worked but produced error messages that sent people to Discord. Embassy, the dominant async embedded framework, shipped all three approaches in different modules.
export async function handler(request: Request): Promise<Response> { const started = Date.now(); const upstream = await fetch(request); const headers = new Headers(upstream.headers); headers.set("x-skarvonix-ms", String(Date.now() - started)); return new Response(upstream.body, { status: upstream.status, headers, });}Async closures collapse that. The AsyncFn family of traits mirrors Fn, FnMut, and FnOnce, and the compiler generates the future type without naming it. Crucially the generated future can borrow from the closure's captures, which is what the older workarounds could not express. Embassy maintainer Dario Nieuwenhuis called it the single largest ergonomics improvement to embedded Rust since async/await itself stabilized, and the framework's 0.8 release, expected in September, removes about 1,400 lines of macro machinery as a result.
What the code looks like now
The practical shape is a function generic over AsyncFnMut that takes a mutable borrow of a peripheral and awaits inside the callback. On the caller side there is no annotation, no Box, and no Pin. For a driver author writing a retry helper around an I2C transaction, this replaces roughly 40 lines of trait definitions with a five line function signature. The generated code compiles to the same state machine you would have written by hand, which the Embassy team verified by comparing disassembly on an STM32H7 target.
Binary size results are the part embedded developers care about most, and they are good. The Rust team's own measurements on a set of 12 no_std sample projects showed a median 3 percent reduction in text section size, because the compiler now sees through the closure and inlines more aggressively than it could through a boxed trait object. Two projects grew slightly. Nobody reported a regression larger than 400 bytes, which for a target with 128 kilobytes of flash is inside the noise most teams tolerate.
The story is rarely the launch. It is what breaks, what ships, and who owns the mess at 2 a.m.
The rest of the release
Const generics in trait bounds is the other stabilization worth reading. You can now write a trait bound that constrains an array length parameter, which matters for anyone building fixed-capacity data structures without allocation. The heapless crate has a branch ready that uses it to remove a family of type-level number tricks, and its maintainer expects the public API to shrink by about a fifth. Cryptography crates including RustCrypto's block cipher traits have similar work queued.
Incremental compilation got attention too. The team reworked how dependency graph nodes are hashed, and reports a 12 to 18 percent reduction in rebuild time on large workspaces after a single-file change. Compiler performance work rarely makes headlines, but for a team running a 400-crate workspace in CI it is worth more than any language feature. Cargo also gained a lockfile version 5 that records the resolver mode, which prevents a class of confusing diffs when developers on the same team have different Cargo versions.
Adoption timing across the ecosystem
The minimum supported Rust version question decides how fast anyone benefits. Tokio's policy keeps six months of compatibility, so async closures cannot appear in its public API until early 2027, though the team confirmed internal use starts immediately. Embassy sets no such policy and will require 1.92 in its next release, which is a defensible choice for a framework whose users control their own toolchain. Larger companies with vendored toolchains and certification requirements will move slower, and some automotive teams are still on 1.81 for ISO 26262 reasons.
The compiler team also flagged one rough edge. Error messages involving async closure lifetimes are still poor, particularly when a closure captures a reference with a shorter lifetime than the future needs. The diagnostics working group has three issues open and expects improvements in 1.94. Anyone hitting a confusing error on this feature should read the tracking issue before assuming they misunderstood the borrow checker, because a fair number of confusing cases are known diagnostic gaps rather than genuine mistakes.
What to expect next
The next feature the embedded community is watching is async drop, which has an accepted RFC and an experimental implementation behind a nightly flag. Without it, cleanup on cancellation still requires blocking code or a manual close call, which is the remaining source of resource leaks in async firmware. The compiler team is candid that async drop touches enough of the language that a 2027 stabilization is optimistic.
Also worth watching is the Rust Project's work on a specification document, which the safety-critical working group needs for certification arguments. Ferrous Systems has maintained a commercial specification for its qualified toolchain, and the upstream effort aims to make that redundant. Progress there decides whether Rust displaces C in aerospace and medical device firmware over the next five years, which is a bigger prize than any single language feature.
Skarvonix will keep following this beat with reporting grounded in how systems behave outside the launch keynote.
- Open Source



