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:
CStr::into_c_string
CString::as_c_str
andCString::into_boxed_c_str
Chain::get_mut
,Chain::get_ref
, andChain::into_inner
Option::get_or_insert_with
andOption::get_or_insert
OsStr::into_os_string
OsString::into_boxed_os_str
Take::get_mut
andTake::get_ref
Utf8Error::error_len
char::EscapeDebug
andchar::escape_debug
compile_error!
f32::from_bits
andf32::to_bits
f64::from_bits
andf64::to_bits
mem::ManuallyDrop
str::from_boxed_utf8_unchecked
str::as_bytes_mut
str::from_utf8_mut
andstr::from_utf8_unchecked_mut
str::get_unchecked
andstr::get_unchecked_mut
str::get
andstr::get_mut
str::into_boxed_bytes
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!