Announcing Rust 1.34.0

The Rust team is happy to announce a new version of Rust, 1.34.0. Rust is a programming language that is empowering everyone to build reliable and efficient software.

If you have a previous version of Rust installed via rustup, getting Rust 1.34.0 is as easy as:

$ rustup update stable

If you don’t have it already, you can get rustup from the appropriate page on our website.

What’s in 1.34.0 stable

The largest feature in this release is the introduction of alternative cargo registries. The release also includes support for ? in documentation tests, some improvements for #[attribute(..)]s, as well as the stabilization of TryFrom. Read on for a few highlights, or see the detailed release notes for additional information.

Alternative cargo registries

Since before 1.0, Rust has had a public crate registry, crates.io. People publish crates with cargo publish and it’s easy to include these crates in the [dependencies] section of your Cargo.toml.

However, not everyone wants to publish their crates to crates.io. People maintaining proprietary/closed-source code cannot use crates.io, and instead are forced to use gitor path dependencies. This is usually fine for small projects, but if you have a lot of closed-source crates within a large organization, you lose the benefit of the versioning support that crates.io has.

With this release, Cargo gains support for alternate registries. These registries coexist with crates.io, so you can write software that depends on crates from both crates.io and your custom registry. Crates on crates.io cannot however depend on external registries.

To use an alternate registry, you must add these lines to your .cargo/config. This file can be in your home directory (~/.cargo/config) or relative to the package directory.

[registries]
my-registry = { index = "https://my-intranet:8080/git/index" }

Depending on a crate from an alternate registry is easy. When specifying dependencies in your Cargo.toml, use the registry key to let Cargo know that you wish to fetch the crate from the alternate registry:

[dependencies]
other-crate = { version = "1.0", registry = "my-registry" }

As a crate author, if you wish to publish your crate to an alternate registry, you first need to save the authentication token into ~/.cargo/credentials with the cargo logincommand:

cargo login --registry=my-registry

You can then use the --registry flag to indicate which registry to use when publishing:

cargo publish --registry=my-registry

There is documentation on how to run your own registry.

? in documentation tests

RFC 1937 proposed adding support for using the ? operator in fn main()#[test]functions, and doctests, allowing them to return Option<T> or Result<T, E>, with error values causing a nonzero exit code in the case of fn main(), and a test failure in the case of the tests.

Support in fn main() and #[test] was implemented many releases ago. However, the support within documentation tests was limited to doctests that have an explicit fn main().

In this release, full support for ? in doctests has been added. Now, you can write this in your documentation tests:

/// ```rust
/// use std::io;
/// let mut input = String::new();
/// io::stdin().read_line(&mut input)?;
/// # Ok::<(), io:Error>(())
/// ```
fn my_func() {}

You still have to specify the error type being used at the bottom of the documentation test.

Custom attributes accept arbitrary token streams

Procedural macros in Rust can define custom attributes that they consume. Until now, such attributes were restricted to being trees of paths and literals according to a specific syntax, like:

#[foo(bar)]
#[foo = "bar"]
#[foo = 0]
#[foo(bar = true)]
#[foo(bar, baz(quux, foo = "bar"))]

Unlike procedural macros, these helper attributes could not accept arbitrary token streams in delimiters, so you could not write #[range(0..10)] or #[bound(T: MyTrait)]. Procedural macro crates would instead use strings for specifying syntaxes like this, e.g. #[range("0..10")]

With this Rust release, custom attributes #[attr($tokens)] now accept arbitrary token streams in $tokens, bringing them on par with macros. If you’re the author of a procedural macro crate, please check if your custom attributes have unnecessary strings in their syntax and if they can be better expressed with token streams.

TryFrom and TryInto

The TryFrom and TryInto traits were stabilized to allow fallible type conversions.

For example, the from_be_bytes and related methods on integer types take arrays, but data is often read in via slices. Converting between slices and arrays is tedious to do manually. With the new traits, it can be done inline with .try_into().

let num = u32::from_be_bytes(slice.try_into()?);

For conversions that cannot fail, such as u8 to u32, the Infallible type was added. This also permits a blanket implementation of TryFrom for all existing Fromimplementations. In the future, we hope to turn Infallible into an alias for the !(never) type.

fn before_exec deprecated in favor of unsafe fn pre_exec

On Unix-like systems, the function CommandExt::before_exec allows you to schedule a closure to be run before exec is invoked.

The closure provided will be run in the context of the child process after a fork. This means that resources, such as file descriptors and memory-mapped regions, may get duplicated. In other words, you can now copy a value of a non-Copy type into a different process while retaining the original in the parent. This makes it possible to cause undefined behavior and break libraries assuming non-duplication.

The function before_exec should therefore have been marked as unsafe. In this release of Rust, we have deprecated fn before_exec in favor of the unsafe fn pre_exec. When calling CommandExt::pre_exec, it is your responsibility to make sure that the closure does not violate library invariants by making invalid use of these duplicates. If you provide a library that is in a similar situation as before_exec, consider deprecating and providing an unsafe alternative as well.

Library stabilizations

In 1.34.0, the set of stable atomic integer types was expanded, with signed and unsigned variants from 8 (AtomicU8) to 64 bits now available.

Previously, non-zero unsigned integer types, e.g. NonZeroU8, were stabilized. This gave Option<NonZeroU8> the same size as u8. With this Rust release, signed versions, e.g. NonZeroI8, have been stabilized.

The functions iter::from_fn and iter::successors have been stabilized. The former allows you to construct an iterator from FnMut() -> Option<T>. To pop elements from a vector iteratively, you can now write from_fn(|| vec.pop()). Meanwhile, the latter creates a new iterator where each successive item is computed based on the preceding one.

Additionally, these APIs have become stable:

See the detailed release notes for more details.

Published by: The Rust Team