Rust 2021 Edition Is Here, and It's the Good Kind of Boring
Rust 1.56.0 and the 2021 Edition shipped today with disjoint closure captures, array IntoIterator, and new macro or-patterns.
Rust shipped its 2021 Edition today, bundled with Rust 1.56.0, and if you blinked you might have missed it — which is honestly the point. This is only the third edition in Rust’s history, after 2015 (the original stable release) and 2018 (modules, NLL, the ergonomics push). Editions in Rust aren’t like major version bumps in most languages. They’re opt-in, they don’t fracture the ecosystem, and crates on different editions still compile together fine. You migrate a crate to a new edition with cargo fix --edition and move on with your life.
So what’s actually in it? The headline feature is disjoint closure captures. Up until now, if a closure touched any field of a struct, it captured the entire struct — which sounds like a minor implementation detail until you’re fighting the borrow checker because your closure only needed self.x but Rust decided to grab all of self anyway, blocking you from mutating self.y elsewhere. As of 2021, closures capture only the specific fields they use. This is one of those changes that fixes a category of borrow-checker headaches that every intermediate Rust developer has run into and quietly worked around with manual field extraction.
Second: arrays finally implement IntoIterator by value. Previously, for x in my_array would iterate over references unless you called .iter() explicitly (or used .into_iter() awkwardly, since that used to fall back to the slice impl). Now you get by-value iteration for free, which is the behavior most people expected from day one. It’s a small thing that’s technically a breaking change in edge cases, which is exactly why it needed an edition boundary rather than shipping silently.
Third, and more niche: macro_rules! gains support for “or patterns” — letting you match multiple pattern variants in a single macro arm instead of duplicating the arm body. Useful if you write a lot of declarative macros, less relevant if you don’t.
None of these are flashy. There’s no new syntax you’ll see plastered across conference talks, no async breakthrough, no const-generics leap forward. That’s very on-brand for how the Rust team runs editions — they’re deliberately conservative, batched every three years or so, and treated as a chance to clean up papercuts rather than reinvent the language. Compare that to how often JavaScript tooling reinvents itself and it’s almost refreshing.
Practically, if you maintain a crate, updating your Cargo.toml to edition = "2021" and running cargo fix --edition should be low-risk for most codebases — the disjoint capture change is the one most likely to actually alter behavior, mainly around Drop timing if you were relying on a closure holding a whole struct alive. Worth a skim through your test suite before you ship it, but I wouldn’t expect fireworks. That’s Rust’s whole pitch, really: evolve without breaking your Tuesday.