Announcing Rust 1.20

Aug. 31, 2017 · The Rust Core Team

The Rust team is happy to announce the latest version of Rust, 1.20.0. Rust is a systems programming language focused on safety, speed, and concurrency.

If you have a previous version of Rust installed, getting Rust 1.20 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, and check out the detailed release notes for 1.20.0 on GitHub.

What's in 1.20.0 stable

In previous Rust versions, you can already define traits, structs, and enums that have "associated functions":

struct Struct;

impl Struct {
    fn foo() {
        println!("foo is an associated function of Struct");
    }
}

fn main() {
    Struct::foo();
}

These are called "associated functions" because they are functions that are associated with the type, that is, they're attached to the type itself, and not any particular instance.

Rust 1.20 adds the ability to define "associated constants" as well:

struct Struct;

impl Struct {
    const ID: u32 = 0;
}

fn main() {
    println!("the ID of Struct is: {}", Struct::ID);
}

That is, the constant ID is associated with Struct. Like functions, associated constants work with traits and enums as well.

Traits have an extra ability with associated constants that gives them some extra power. With a trait, you can use an associated constant in the same way you'd use an associated type: by declaring it, but not giving it a value. The implementor of the trait then declares its value upon implementation:

trait Trait {
    const ID: u32;
}

struct Struct;

impl Trait for Struct {
    const ID: u32 = 5;
}

fn main() {
    println!("{}", Struct::ID);
}

Before this release, if you wanted to make a trait that represented floating point numbers, you'd have to write this:

trait Float {
    fn nan() -> Self;
    fn infinity() -> Self;
    ...
}

This is slightly unwieldy, but more importantly, because they're functions, they cannot be used in constant expressions, even though they only return a constant. Because of this, a design for Float would also have to include constants as well:

mod f32 {
    const NAN: f32 = 0.0f32 / 0.0f32;
    const INFINITY: f32 = 1.0f32 / 0.0f32;

    impl Float for f32 {
        fn nan() -> Self {
            f32::NAN
        }
        fn infinity() -> Self {
            f32::INFINITY
        }
    }
}

Associated constants let you do this in a much cleaner way. This trait definition:

trait Float {
    const NAN: Self;
    const INFINITY: Self;
    ...
}

Leads to this implementation:

mod f32 {
    impl Float for f32 {
        const NAN: f32 = 0.0f32 / 0.0f32;
        const INFINITY: f32 = 1.0f32 / 0.0f32;
    }
}

much cleaner, and more versatile.

Associated constants were proposed in RFC 195, almost exactly three years ago. It's been quite a while for this feature! That RFC contained all associated items, not just constants, and so some of them, such as associated types, were implemented faster than others. In general, we've been doing a lot of internal work for constant evaluation, to increase Rust's capabilities for compile-time metaprogramming. Expect more on this front in the future.

We've also fixed a bug with the include! macro in documentation tests: for relative paths, it erroneously was relative to the working directory, rather than to the current file.

See the detailed release notes for more.

Library stabilizations

There's nothing super exciting in libraries this release, just a number of solid improvements and continued stabilizing of APIs.

The unimplemented! macro now accepts messages that let you say why something is not yet implemented.

We upgraded to Unicode 10.0.0.

min and max on floating point types were rewritten in Rust, no longer relying on cmath.

We are shipping mitigations against Stack Clash in this release, notably, stack probes, and skipping the main thread's manual stack guard on Linux. You don't need to do anything to get these protections other than using Rust 1.20.

We've added a new trio of sorting functions to the standard library: slice::sort_unstable_by_key, slice::sort_unstable_by, and slice::sort_unstable. You'll note that these all have "unstable" in the name. Stability is a property of sorting algorithms that may or may not matter to you, but now you have both options! Here's a brief summary: imagine we had a list of words like this:

rust
crate
package
cargo

Two of these words, cargo and crate, both start with the letter c. A stable sort that sorts only on the first letter must produce this result:

crate
cargo
package
rust

That is, because crate came before cargo in the original list, it must also be before it in the final list. An unstable sort could provide that result, but could also give this answer too:

cargo
crate
package
rust

That is, the results may not be in the same original order.

As you might imagine, fewer constraints often means faster results. If you don't care about stability, these sorts may be faster for you than the stable variants. As always, best to check both and see! These functions were added by RFC 1884, if you'd like more details, including benchmarks.

Additionally, the following APIs were also stabilized:

See the detailed release notes for more.

Cargo features

Cargo has some nice upgrades this release. First of all, your crates.io authentication token used to be stored in ~/.cargo/config. As a configuration file, this would often be stored with 644 permissions, that is, world-readable. But it has a secret token in it. We've moved the token to ~/.cargo/credentials, so that it can be permissioned 600, and hidden from other users on your system.

If you used secondary binaries in a Cargo package, you know that they're kept in src/bin. However, sometimes, you want multiple secondary binaries that have significant logic; in that case, you'd have src/bin/client.rs and src/bin/server.rs, and any submodules for either of them would go in the same directory. This is confusing. Instead, we now conventionally support src/bin/client/main.rs and src/bin/server/main.rs, so that you can keep larger binaries more separate from one another.

See the detailed release notes for more.

Contributors to 1.20.0

Many people came together to create Rust 1.20. We couldn't have done it without all of you. Thanks!