2. Closures in Rust 2021 will capture only the fields of an object you use, instead of the entire object. This should result in fewer fights with the borrow checker:
3/17
3. In Rust 2021, `$x:pat` in macro_rules now accepts patterns that include a `|`, making your macro rules easier to write:
4/17
4. Specifying `edition = "2021"` in your Cargo.toml implies `resolver = "2"`, when not explicitly given.
5. In Rust 2021, you don't have to import the TryFrom, TryInto and FromIterator traits anymore. They are now part of the prelude, which is automatically imported into all your modules:
6/17
6. The panic!() (and assert) macros in Rust 2021 no longer behave inconsistently when given only one argument. This unblocks a feature that will be available in a few versions from now: implicit format arguments.
7/17
7. We reserved some syntax for identifiers and literals with prefixes in Rust 2021. This syntax doesn't mean anything *yet*, but reserving it means we can start giving meaning to it in the (near?) future:
8/17
And finally the last change that's part of the 2021 edition:
8. Some old syntax that's been deprecated for a while is completely removed in Rust 2021. This means we can use that syntax for something else in the future. (Maybe we can use `...` for variadic generics.)
9/17
Then let's continue with the changes in Rust 1.56 that are available in all editions:
1. Extend<(A, B)> for (Extend<A>, Extend<B>)
It allows splitting an iterator over tuples into separate collections, a bit like the opposite of .zip():
10/17
2. From<array> for BTreeMap, BTreeSet, HashMap, HashSet, VecDeque, LinkedList, and BinaryHeap.
You can now use e.g. BTreeMap::from(..) to make a collection with directly the contents you want:
11/17
3. You can now combine `@` bindings with regular pattern bindings. That means you can now give a name to an object _and give a name to some parts of it_ at the same time:
12/17
4. BufWriter::into_parts()
BufWriter::into_inner() will try to flush the buffer before giving you back the underlying Write object, which can fail.
BufWriter::into_parts() cannot fail and gives you the Write object and the unflushed buffer, so you can handle it manually:
13/17
5. A new .shrink_to() method on Vec, String, PathBuf, VecDeque, HashSet, etc.
This allows you to *reduce* the .capacity() of a collection. It is basically the opposite of .reserve():
14/17
6. const mem::transmute() π¬
You can now use std::mem::transmute to do horrible things in a const fn:
15/17
And finally, a new Cargo feature:
7. You can now specify the minimum supported Rust version in your Cargo.toml:
rust-version = "1.56.0"
If specified, Cargo will give users of your crate a clear error when their version of Rust is too old:
16/17
And that's the end of this thread!β¨
For a more complete list of changes in Rust 1.56, check the release notes:
ππ¦ Just an hour ago, #rustlang 1.66.0 was released!
As usual, here's a thread with some of the highlights. π§΅
1/12
Rust 1.66 comes with std::hint::black_box(), a function that does nothing. However, the compiler tries its very best to pretend it doesn't know what it does.
It is useful in benchmarks, to prevent the compiler from optimizing your entire benchmark away.
2/12
The Option type got a new method: Option::unzip(). It's basically the opposite of Option::zip(): it splits an Option of a pair into a pair of Options.
Rust now has a new async-related trait: IntoFuture.
The .await syntax be used on anything that implements IntoFuture. (Similar to how, with a for loop, you can iterate over anything that implements IntoIterator.)
This allows types to provide easier async interfaces.
2/15
Today's Rust release also comes with two more async-related tools:
The std::future::poll_fn function allows you to easily create a future from a closure (like iter::from_fn for iterators).
The std::task::ready!() macro extracts a Poll::Ready, or returns early on Pending.
Cargo now has 'cargo add' built-in: a (sub)command to add a crate to your Cargo.toml. It automatically looks up the latest version, and shows you the available features of the crate.
See `cargo add --help` for more details.
2/9
On Linux and several BSDs, std::sync's Mutex, RwLock, and Condvar now no longer do any allocations. They used to be (heap-allocated) wrappers around pthread lock types, but have been replaced by a minimal, more efficient, futex-based implementations.
π¦ As of Rust 1.62 (going into beta this week), std::sync::Mutex, RwLock, and Condvar no longer do any allocations on Linux. π
Benchmarking locks is extremely tricky, as their performance depends heavily on the exact use case, but there are very noticable differences:
std's Mutex basically used to contain a Pin<Box<pthread_mutex_t>>, where the pinned Box was only necessary because pthread_mutex_t is not guaranteed movable. The new Mutex no longer uses pthread, and instead directly uses the futex syscall, making it smaller and more efficient.
Also, the new RwLock on Linux prefers writers, which prevents writer starvation. pthread_rwlock_t prefers readers by default, to allow recursive read locking. Rust's RwLock does not make recursion guarantees, and on several platforms (including Windows) already preferred writers.