ADR-220: Edition 2024 for Our Crates and for the Emitted Code

Status: Superseded by ADR-305 — its D1-D4 are D4-D7 there Date: September 26, 2026 Target Version: Nikaia 0.0.201 Answers: the owner’s is the codebase compatible with Rust 1.94 and Edition 2024’s stricter scoping at .await points, or do we need to change them? 1.94 as the new minimum would be fine Related: ADR-219 (the floor, which stays 1.88), ADR-218 (the unsafe crates), ADR-298 (the names the language below reserves)

1. Context

Edition 2024 changes when some values are dropped. That matters at .await, because a guard or borrow that lives past a pause is held for the whole pause and makes a future !Send. There are two changes:

Both make values live shorter, never longer. So a program that compiled under 2021 cannot start holding a lock across an .await because of them. What can change is an order of Drop that someone relied on.

2. What was measured

Rust 1.94.1’s migration lints (cargo fix --edition) were run over crates/nikaia, crates/nikaia-std, crates/orchestrator and the six crates under crates/unsafe/:

lint hits verdict
if_let_rescope 0 —
tail_expr_drop_order 10 benign: each drops a temporary (a Result, an Option just taken, a poll’s return value) that holds no lock and has no Drop anyone observes. Three are in the runtime (net.rs accept, exec.rs poll and the task’s value.take()), none across an .await
impl_trait_overcaptures 1 branch_values in the emitter, + use<'_> added
edition_2024_expr_fragment_specifier 1 a diagnostics macro, now expr_2021

Then the edition was switched and the whole suite was run, including every program the tests emit, compiled as 2024. Two things broke, both in the emitted code and neither about .await:

Clippy under 2024 also asks for let chains where two if let were nested. That is style, applied with clippy --fix, and rustfmt’s 2024 style sorts imports differently. Neither changes behaviour.

3. Decisions

D1 — No .await point needs a change.

This is the answer to the question. The drop-order changes make temporaries live shorter. None of the ten places holds anything across a pause, and the suite, which runs the runtime’s async paths, passes unchanged.

D2 — Our crates are Edition 2024.

This covers crates/nikaia, crates/nikaia-std, crates/orchestrator and every crate under crates/unsafe/. The benchmark crates under benches/ stay

  1. They are measurements, not the product, and an edition is per crate.

D3 — The emitted code is Edition 2024.

This covers every generated Cargo.toml, the grammar runner’s manifest, and the tests’ rustc --edition. The emitter writes unsafe extern "C". gen joins the emitter’s list of words the language below reserves, and the sweep in tests/reserved_below.rs compiles it escaped in every position.

D4 — The floor stays 1.88.

Edition 2024 needs Rust 1.85, and let chains need 1.88, which is already the floor (ADR-219). Nothing measured needs 1.94, so raising the floor would lock out 1.88 through 1.93 for nothing. scripts/check-floor.sh passes on 1.88.0 with everything on 2024.

4. What is built

All of it, in 0.0.201.

This site is open source. Improve this page.