The new edition of Rust is here. The edition 2021 of Rust have many interesting changes in it. Let us have a look at some of the changes in edition 2021.
Additions to the prelude
- The
TryInto
,TryFrom
andFromIterator
traits are now part of the prelude. - This might make calls to trait methods ambiguous which could make some code fail to compile.
However, adding a trait to the prelude can break existing code in a subtle way. For example, a call to x.try_into()
which comes from a MyTryInto
trait might fail to compile if std
‘s TryInto
is also imported, because the call to try_into
is now ambiguous and could come from either trait. This is the reason, edition 2021 has not added TryInto
to the prelude yet, since there is a lot of code that would break this way.
As a solution, Rust 2021 will use a new prelude. It’s identical to the current one, except for three new additions:
std::convert::TryInto
std::convert::TryFrom
std::iter::FromIterator
Disjoint capture in closures
|| a.x + 1
now captures onlya.x
instead ofa
.- This can cause things to be dropped at different times or affect whether closures implement traits like
Send
orClone
.- If possible changes are present,
cargo fix
will insert statements likelet _ = &a
to force a closure to capture the entire variable.
- If possible changes are present,
Panic macro consistency
panic!(..)
now always usesformat_args!(..)
, just likeprintln!()
.panic!("{")
is no longer , without escaping the{
as{{
.panic!(x)
is no longer accepted ifx
is not a string literal.- Use
std::panic::panic_any(x)
to panic with a non-string payload. - Or use
panic!("{}", x)
to usex
‘sDisplay
implementation.
- Use
- The same applies to
assert!(expr, ..)
.
Reserving syntax
any_identifier#
,any_identifier"..."
, andany_identifier'...'
are now reserved syntax, and no longer tokenize.- This is mostly relevant to macros. E.g.
quote!{ #a#b }
is no longer accepted. - It doesn’t treat keywords specially, so e.g.
match"..." {}
is no longer accepted. - Insert whitespace between the identifier and the subsequent
#
,"
, or'
to avoid errors. - Edition migrations will help you insert whitespace in such cases.
To make space for new syntax in the future, we’ve decided to reserve syntax for prefixed identifiers and literals: prefix#identifier
, prefix"string"
, prefix'c'
, and prefix#123
, where prefix
can be any identifier. (Except those prefixes that already have a meaning, such as b'...'
(byte strings) and r"..."
(raw strings).)
Or patterns in macro-rules
- How patterns work in
macro_rules
macros changes slightly:$_:pat
inmacro_rules
now matches usage of|
too: e.g.A | B
.- The new
$_:pat_param
behaves like$_:pat
did before; it does not match (top level)|
. $_:pat_param
is available in all editions.
This edition has extended Patterns to support | nested anywhere in the pattern. This enables you to write Some(1 | 2) instead of Some(1) | Some(2).
IntoIterator for arrays
- Arrays implement
IntoIterator
in all editions. - Calls to
IntoIterator::into_iter
are hidden in Rust 2015 and Rust 2018 when using method call syntax (i.e.,array.into_iter()
). So,array.into_iter()
still resolves to(&array).into_iter()
as it has before. array.into_iter()
changes meaning to be the call toIntoIterator::into_iter
in Rust 2021.
Default Cargo feature resolver
edition = "2021"
implies resolver = "2"
in Cargo.toml
.
Warnings promoted to errors
Code that triggered the bare_trait_objects
and ellipsis_inclusive_range_patterns
lints will error in Rust 2021. These two existing lints are becoming hard errors in Rust 2021, but these lints will remain warnings in older editions.
If you want to read more content like this? Subscribe to Rust Times Newsletter and receive insights and latest updates, bi-weekly, straight into your inbox. Subscribe to Rust Times Newsletter: https://bit.ly/2Vdlld7.



