Rust's Third Edition Is Here, and It's Barely Noticeable (That's the Point)
Rust 1.56 shipped the 2021 Edition with small, opt-in changes that quietly smooth out years of rough edges.
Rust shipped its 2021 Edition a couple weeks back, bundled into the 1.56 release, and if you blinked you might have missed it. That’s not a knock — it’s the whole design philosophy. This is only the third edition in Rust’s history, after 2015 and 2018, and true to form it doesn’t rewrite the language. It nudges it.
For anyone unfamiliar with how Rust does editions: unlike a lot of languages that either never break compatibility or break it whenever they feel like it, Rust bundles breaking-ish changes into opt-in editions that you declare in your Cargo.toml. Crates on different editions can still depend on each other and compile together. It’s a clever way to let the language evolve syntax and defaults without fracturing the ecosystem into “old code” and “new code” camps that can’t talk to each other.
So what actually changed in 2021? A handful of things, none of them flashy, all of them the kind of fix that makes you go “wait, it didn’t already work that way?”
The one I think matters most day-to-day is disjoint closure captures. Previously, if you had a closure that borrowed struct.field_a, Rust would capture the entire struct, not just the field it needed. That meant you’d hit baffling borrow-checker errors trying to use struct.field_b elsewhere in the same scope, even though there was no real conflict. Now closures capture only the specific fields they touch. It’s the kind of change that won’t show up in a changelog headline but will quietly stop annoying you on a Tuesday afternoon.
Arrays also finally get proper IntoIterator support, so you can write for x in my_array and get owned values instead of having to reach for .iter() first. Small thing, but it’s the kind of small thing that trips up newcomers constantly, and removing that friction matters more than it sounds.
There’s also an expanded prelude — a couple of new traits get auto-imported so you don’t need explicit use statements for them — and updated panic macros that clean up formatting edge cases.
None of this is revolutionary, and that seems intentional. The Rust team has been pretty consistent about not wanting “big rewrite” energy in its editions; the goal is stability plus steady sanding-down of sharp edges. Compare that to how some ecosystems treat major version bumps as an excuse to break everything at once, and it’s a nice contrast.
What I like about this release cadence is what it signals about Rust’s maturity. A language in its “everything is still being figured out” phase ships editions full of syntax changes and new keywords. A language that’s settling into long-term use ships editions full of ergonomics fixes for the corners real projects keep bumping into. Disjoint closures and array iteration are exactly the kind of thing you only notice you needed after millions of lines of code have been written and the community has spent years cataloguing what’s annoying.
If you’re maintaining a crate, updating is genuinely low-risk — it’s opt-in per crate, the changes are backward compatible in spirit even if technically edition-gated, and cargo fix --edition will migrate most of the mechanical parts for you. Worth doing sooner rather than later just to get the closure capture improvements, honestly.