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,TryFromandFromIteratortraits 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::TryIntostd::convert::TryFromstd::iter::FromIterator
Disjoint capture in closures
|| a.x + 1now captures onlya.xinstead ofa.- This can cause things to be dropped at different times or affect whether closures implement traits like
SendorClone.- If possible changes are present,
cargo fixwill insert statements likelet _ = &ato 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 ifxis not a string literal.- Use
std::panic::panic_any(x)to panic with a non-string payload. - Or use
panic!("{}", x)to usex‘sDisplayimplementation.
- 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_rulesmacros changes slightly:$_:patinmacro_rulesnow matches usage of|too: e.g.A | B.- The new
$_:pat_parambehaves like$_:patdid before; it does not match (top level)|. $_:pat_paramis 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
IntoIteratorin all editions. - Calls to
IntoIterator::into_iterare 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_iterin 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.
