What Is New in Rust 1.56
| Category | Highlights |
|---|---|
| New Features | Rust 2021 edition (disjoint capture, array .into_iter() by value, macro_rules or-patterns, prelude now includes TryInto/TryFrom/FromIterator, panic! always expects a format string, reserved syntax for ident#, ident\"...\", ident'...'); Cargo rust-version field; new @-pattern bindings that allow simultaneous whole-value and field bindings. |
| Improvements | Default Cargo feature resolver upgraded to version 2, providing faster and more predictable dependency resolution. |
| Breaking Changes | panic! macro now requires a format string (like println!); warnings bare_trait_objects and ellipsis_inclusive_range_patterns are promoted to hard errors; array .into_iter() now yields owned items instead of references, which may affect existing loops. |
What are the key changes introduced by the Rust 2021 edition?
Rust 2021 brings a set of quality-of-life improvements that are opt-in via the edition flag.
- Disjoint capture in closures: closures now capture only the fields they actually use.
// 2021 edition - works without manual extraction let a = SomeStruct::new(); let c = || println!("{}", a.y); c(); - IntoIterator for arrays:
array.into_iter()now iterates by value.let arr = [1, 2, 3]; for x in arr.into_iter() { println!("{}", x); // x is owned i32 } - Macro-rules or-patterns: top-level
A|Bcan now appear directly in:patpositions. - Prelude expansion:
TryInto,TryFrom, andFromIteratorare automatically in scope. - Panic macro format strings:
panic!("msg")now requires a format string, matchingprintln!()semantics. - Reserved identifier syntax:
ident#,ident"...", andident'...'are now reserved for future use. - Warnings turned into errors:
bare_trait_objectsandellipsis_inclusive_range_patternsare now hard errors.
In practice, most teams can adopt the edition with a single cargo fix --edition run, and the compiler will insert shim code where the new semantics would otherwise change drop order.
How does the new Cargo rust-version field affect crate publishing?
The rust-version field lets you declare the minimum compiler version a crate supports.
- Add
rust-version = "1.56"under the[package]section ofCargo.toml. - Cargo will emit an early error if a user tries to compile the crate with an older toolchain.
- This check happens before dependency resolution, helping catch incompatibilities early.
Most teams use this field to guarantee that CI pipelines run on a known baseline, reducing "works on my machine" surprises.
What is the new binding syntax with @ patterns and why does it matter?
Rust 1.56 re-introduces the ability to bind a whole value while simultaneously destructuring part of it.
struct Matrix { data: Vec, row_len: usize }
let matrix @ Matrix { row_len, .. } = get_matrix(); // binds whole struct to `matrix` and extracts `row_len`
This eliminates the need for a separate let-statement or a two-step destructuring, making pattern matches more concise and expressive. It is safe after extensive borrow-checker improvements.
What breaking changes should I watch out for when upgrading to Rust 1.56?
Upgrading to 1.56 may surface a few hard errors that were previously only warnings.
- Panic macro format strings:
panic!("msg")without a format string now fails to compile. - Warnings promoted to errors: using
bare_trait_objectsor ellipsis in inclusive range patterns (..=) will stop the build. - Array iteration semantics: code that relied on
array.into_iter()yielding references must be updated to handle owned values.
Most projects can address these issues by adding explicit format strings to panic! calls, fixing the warned-about patterns, or adjusting loops to borrow the array when needed.
Frequently Asked Questions
Do I need to change my Cargo.toml to use the new rust-version field?
You only need to add a rust-version key under [package] if you want Cargo to enforce a minimum compiler version.
Will existing code compile after upgrading to Rust 1.56?
Most code will compile unchanged, but you may need to address warnings that have become errors such as bare_trait_objects.
How do I enable the Rust 2021 edition for an existing crate?
Add edition = "2021" to the Cargo.toml [package] section or run cargo fix --edition.
What does disjoint capture in closures change?
Closures now capture only the fields they actually use, so the example let c = || println!("{}", a.y); works without manually extracting a.y.
How does array.into_iter() behave now?
It iterates by value, yielding owned elements instead of references.
Can I see a quick example of the new @ pattern binding?
let matrix @ Matrix { row_len, .. } = get_matrix(); binds the whole struct to matrix while also extracting row_len.