Series: The Rust Annals
Vol. I Issue 40 nlopes.dev
Announcing Rust 1.39.0
Stabilization of async functions and .await, a landmark addition that fundamentally transforms Rust's asynchronous programming model and ecosystem readiness.
The .await is over, async fns are here
Previously in Rust 1.36.0, we announced that the Future trait is here. Back then, we noted that:
With this stabilization, we hope to give important crates, libraries, and the ecosystem time to prepare for
async/.await, which we’ll tell you more about in the future.
A promise made is a promise kept. So in Rust 1.39.0, we are pleased to announce that async / .await is stabilized! Concretely, this means that you can define async functions and blocks and .await them.
An async function, which you can introduce by writing async fn instead of fn, does nothing other than to return a Future when called. This Future is a suspended computation which you can drive to completion by .awaiting it. Besides async fn, async { ... } and async move { ... } blocks, which act like closures, can be used to define “async literals”.
For more on the release of async / .await, read Niko Matsakis’s blog post.
References to by-move bindings in match guards
When pattern matching in Rust, a variable, also known as a “binding”, can be bound in the following ways:
-
by-reference, either immutably or mutably. This can be achieved explicitly e.g. through
ref my_varorref mut my_varrespectively. Most of the time though, the binding mode will be inferred automatically. -
by-value – either by-copy, when the bound variable’s type implements
Copy, or otherwise by-move.
Previously, Rust would forbid taking shared references to by-move bindings in the if guards of match expressions. This meant that the following code would be rejected:
fn main() {
let array: Box<[u8; 4]> = Box::new([1, 2, 3, 4]);
match array {
nums
// ---- `nums` is bound by move.
if nums.iter().sum::<u8>() == 10
// ^------ `.iter()` implicitly takes a reference to `nums`.
=> {
drop(nums);
// ----------- `nums` was bound by move and so we have ownership.
}
_ => unreachable!(),
}
}
With Rust 1.39.0, the snippet above is now accepted by the compiler. We hope that this will give a smoother and more consistent experience with match expressions overall.
Attributes on function parameters
With Rust 1.39.0, attributes are now allowed on parameters of functions, closures, and function pointers. Whereas before, you might have written:
#[cfg(windows)]
fn len(slice: &[u16]) -> usize {
slice.len()
}
#[cfg(not(windows))]
fn len(slice: &[u8]) -> usize {
slice.len()
}
…you can now, more succinctly, write:
fn len(
#[cfg(windows)] slice: &[u16], // This parameter is used on Windows.
#[cfg(not(windows))] slice: &[u8], // Elsewhere, this one is used.
) -> usize {
slice.len()
}
The attributes you can use in this position include:
-
Conditional compilation:
cfgandcfg_attr -
Controlling lints:
allow,warn,deny, andforbid -
Helper attributes used by procedural macro attributes applied to items.
Our hope is that this will be used to provide more readable and ergonomic macro-based DSLs throughout the ecosystem.
Borrow check migration warnings are hard errors in Rust 2018
In the 1.36.0 release, we announced that NLL had come to Rust 2015 after first being released for Rust 2018 in 1.31.
As noted in the 1.36.0 release, the old borrow checker had some bugs which would allow memory unsafety. These bugs were fixed by the NLL borrow checker. As these fixes broke some stable code, we decided to gradually phase in the errors by checking if the old borrow checker would accept the program and the NLL checker would reject it. If so, the errors would instead become warnings.
With Rust 1.39.0, these warnings are now errors in Rust 2018. In the next release, Rust 1.40.0, this will also apply to Rust 2015, which will finally allow us to remove the old borrow checker, and keep the compiler clean.
If you are affected, or want to hear more, read Niko Matsakis’s blog post.
More const fns in the standard library
With Rust 1.39.0, the following functions became const fn:
Vec::new,String::new, andLinkedList::newstr::len,[T]::len, andstr::as_bytesabs,wrapping_abs, andoverflowing_abs
Additions to the standard library
In Rust 1.39.0 the following functions were stabilized: