-
Notifications
You must be signed in to change notification settings - Fork 301
1.31 announcement #295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
1.31 announcement #295
Changes from 4 commits
8f8dfbd
3f2abea
7ca425a
3ca3a1a
3d22329
4a12def
27e8405
30ae7d4
652eb15
90b0dbb
41a891c
e76a634
1539291
e790467
df9d156
397e1c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,338 @@ | ||
--- | ||
layout: post | ||
title: "Announcing Rust 1.31" | ||
author: The Rust Core Team | ||
--- | ||
|
||
The Rust team is happy to announce a new version of Rust, 1.31.0. Rust is a | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
systems programming language focused on safety, speed, and concurrency. | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
If you have a previous version of Rust installed via rustup, getting Rust | ||
1.31.0 is as easy as: | ||
|
||
```bash | ||
$ rustup update stable | ||
``` | ||
|
||
If you don't have it already, you can [get `rustup`][install] from the | ||
appropriate page on our website, and check out the [detailed release notes for | ||
1.31.0][notes] on GitHub. | ||
|
||
[install]: https://www.rust-lang.org/install.html | ||
[notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1310-2018-12-06 | ||
|
||
## What's in 1.31.0 stable | ||
|
||
Rust 1.31 may be the most exciting release since Rust 1.0! Included in this release is the | ||
first iteration of "Rust 2018," but there's more than just that! This is going to be a long | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
post, so here's a table of contents: | ||
|
||
* [Rust 2018](#rust-2018) | ||
* [Non-lexical lifetimes](#non-lexical-lifetimes) | ||
* [Module system changes](#module-system-changes) | ||
* [More lifetime elision rules](#more-lifetime-elision-rules) | ||
* [`const fn`](#const-fn) | ||
* [Tool Lints](#tool-lints) | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* [Library stabilizations](#library-stabilizations) | ||
* [Cargo features](#cargo-features) | ||
* [Contributors](#contributors-to-1310) | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### Rust 2018 | ||
|
||
We wrote about Rust 2018 [first in | ||
March](https://blog.rust-lang.org/2018/03/12/roadmap.html), [and then in | ||
July](https://blog.rust-lang.org/2018/07/27/what-is-rust-2018.html). | ||
For some more background about the *why* of Rust 2018, please go read those | ||
posts; there's a lot to cover in the release announcement, and so we're going | ||
to focus on the *what* here. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO: link to Lin's post here, for a graphic explainer of what Rust 2018 is all about. |
||
|
||
Let's create a new project with Cargo: | ||
|
||
```console | ||
$ cargo new foo | ||
``` | ||
|
||
Here's the contents of `Cargo.toml`: | ||
|
||
```toml | ||
[package] | ||
name = "foo" | ||
version = "0.1.0" | ||
authors = ["Your Name <[email protected]>"] | ||
edition = "2018" | ||
|
||
[dependencies] | ||
``` | ||
|
||
A new key has been added under `[package]`: `edition`. You'll note it's been | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
set to `2018`. You can also set it to `2015`, which is the default if the key | ||
does not exist. | ||
|
||
By using Rust 2018, you unlock some new features that are not allowed in Rust 2015. | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
And eventually, we'll be turning on some new warnings that help you use these | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
new features more effectively, as well. | ||
|
||
But it's important to note that each package you use can be in either 2015 or | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
2018 mode, and they work seamlessly together. Your 2018 project can use 2015 | ||
dependencies, and a 2015 project can use 2018 dependencies. This ensures that | ||
we don't split the ecosystem, and all of these new things are opt-in, | ||
preserving compatibility for existing code. Furthermore, when you do choose | ||
to migrate Rust 2015 code to Rust 2018, the changes can be made | ||
automatically, via `cargo fix`. | ||
|
||
What kind of new features, you may ask? Well, first, features get added to | ||
Rust 2015 unless they require some sort of incompatibility with 2015's | ||
features. As such, most of the language is available everywhere. You can | ||
check out [the edition | ||
guide](https://doc.rust-lang.org/nightly/edition-guide) to check each | ||
feature's minimum `rustc` version as well as edition requirements. However, | ||
there are a few big-ticket features we'd like to mention here: non-lexical | ||
lifetimes, and some module system improvements. | ||
|
||
#### Non-lexical lifetimes | ||
|
||
If you've been following Rust's development over the past few years, you may | ||
have heard the term "NLL" or "non-lexical lifetimes" thrown around. This is | ||
jargon, but it has a straightforward translation into simpler terms: the | ||
borrow checker has gotten smarter, and now accepts some valid code that it | ||
previously rejected. Consider this example: | ||
|
||
```rust | ||
fn main() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if we should use, or at least mention, a more real example? Maybe we should just leave it for @nikomatsakis's post, though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A "mutate the original variable at the end of a
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd like to stick to the simple example for now, unless we feel really strongly about it. There's a lot in this post already, and keeping it straightforward is more important than being hyper realistic, I think. If people feel super strongly I'm willing to change it though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @steveklabnik I don't feel super strongly about this. But I'd like to point out that we're likely to get a fair number of people from outside the normal Rust community reading this, who might not have the context for why such a change is important/useful/interesting. If you're worried about length, perhaps we could link out to a blog post or to the RFC instead of including a more realistic example in the post? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did link to the edition guide, which has the full details of everything; maybe we need another one? |
||
let mut x = 5; | ||
|
||
let y = &x; | ||
|
||
let z = &mut x; | ||
} | ||
``` | ||
|
||
In older Rust, this is a compile-time error: | ||
|
||
```text | ||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable | ||
--> src/main.rs:5:18 | ||
| | ||
4 | let y = &x; | ||
| - immutable borrow occurs here | ||
5 | let z = &mut x; | ||
| ^ mutable borrow occurs here | ||
6 | } | ||
| - immutable borrow ends here | ||
``` | ||
|
||
This is because lifetimes follow "lexical scope"; that is, the borrow from `y` | ||
is considered to be held until `y` goes out of scope at the end of main, even | ||
though we never use `y` again. This code is fine, but the borrow checker could | ||
not handle it. | ||
|
||
Today, this code will compile just fine. | ||
|
||
What if we did use `y`, like this for example: | ||
|
||
```rust | ||
fn main() { | ||
let mut x = 5; | ||
let y = &x; | ||
let z = &mut x; | ||
|
||
println!("y: {}", y); | ||
} | ||
``` | ||
|
||
Older Rust will give you this error: | ||
|
||
```text | ||
rror[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
--> src/main.rs:5:18 | ||
| | ||
4 | let y = &x; | ||
| - immutable borrow occurs here | ||
5 | let z = &mut x; | ||
| ^ mutable borrow occurs here | ||
... | ||
8 | } | ||
| - immutable borrow ends here | ||
``` | ||
|
||
With Rust 2018, this error changes for the better: | ||
|
||
```text | ||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable | ||
--> src/main.rs:5:13 | ||
| | ||
4 | let y = &x; | ||
| -- immutable borrow occurs here | ||
5 | let z = &mut x; | ||
| ^^^^^^ mutable borrow occurs here | ||
6 | | ||
7 | println!("y: {}", y); | ||
| - borrow later used here | ||
``` | ||
|
||
Instead of pointing to where `y` goes out of scope, it shows you where the | ||
conflicting borrow occurs. This makes these sorts of errors far easier to | ||
debug. | ||
|
||
In Rust 1.31, this feature is exclusive to Rust 2018. We plan to backport it | ||
to Rust 2015 at a later date. | ||
|
||
#### Module system changes | ||
|
||
The module system can be a struggle for people first learning Rust. | ||
Everyone has their own things that take time to master, of course, but | ||
there's a root cause for why it's so confusing to many: while there are | ||
simple and consistent rules defining the module system, their consequences | ||
can feel inconsistent, counterintuitive and mysterious. | ||
|
||
As such, the 2018 edition of Rust introduces a few new module system | ||
features, but they end up simplifying the module system, to make it more | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
clear as to what is going on. | ||
|
||
Here's a brief summary: | ||
|
||
* `extern crate` is no longer needed in 99% of circumstances. | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* You can import macros with `use`, rather than a `#[macro_use]` attribute. | ||
* Absolute paths begin with a crate name, where the keyword `crate` refers to the current crate. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe clarify: all paths in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not 100% sure what you're asking me to tweak.
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* A `foo.rs` and `foo/` subdirectory may coexist; `mod.rs` is no longer needed when placing submodules in a subdirectory. | ||
|
||
These may seem like arbitrary new rules when put this way, but the mental | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feels a bit underwhemling. I'm wondering if we can get across a bit more about why this is an improvement. For example, we could talk about how this eliminates the confusion around paths working differently at the top level module vs submodules. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was worried about the post being too long.... doing that adds a lot of length. I agree that it feels underwhelming though... |
||
model is now significantly simplified overall. | ||
|
||
There's a *lot* of details here, so please read [the edition | ||
guide](https://doc.rust-lang.org/nightly/edition-guide/rust-2018/module-system/path-clarity.html) | ||
for full details. | ||
|
||
### More lifetime elision rules | ||
|
||
Let's talk about a feature that's available in both editions: we've added | ||
some additional elision rules for `impl` blocks and function definitions. | ||
Code like this: | ||
|
||
```rust | ||
impl<'a> Reader for BufReader<'a> { | ||
// methods go here | ||
} | ||
` | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
can now be written like this: | ||
|
||
```rust | ||
impl Reader for BufReader<'_> { | ||
// methods go here | ||
} | ||
``` | ||
|
||
The `'_` lifetime still shows that `BufReader` takes a parameter, but we | ||
don't need to create a name for it anymore. | ||
|
||
Lifetimes are still required to be defined in structs. We're considering | ||
some options here in the future, but have no concrete plans yet. | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### `const fn` | ||
|
||
There's several ways to define a function in Rust: a regular function with | ||
`fn`, an unsafe function with `unsafe fn`, an external function with `extern fn`. | ||
This release adds a new way to qualify a function: `const fn`. It looks like | ||
this: | ||
|
||
```rust | ||
const fn foo(x: i32) -> i32 { | ||
x + 1 | ||
} | ||
``` | ||
|
||
A `const fn` can be called like a regular function, but it can also be used | ||
in any constant context. When it is, it is evaluated at compile time, rather | ||
than at run time. As an example: | ||
|
||
```rust | ||
const SIX: i32 = foo(5); | ||
``` | ||
|
||
This will execute `foo` at compile time, and set `SIX` to `6`. | ||
|
||
`const fn`s cannot do everything that normal `fn`s can do; they must | ||
have deterministic output. This is important for soundness reasons. | ||
Currently, `const fn`s can do a minimal subset of operations. Here's | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks accurate / what we said in the tracking issue / reference; |
||
some examples of what you can do: | ||
|
||
* Arithmetic and comparison operators on integers | ||
* All boolean operators except for `&&` and `||` | ||
* Constructing arrays, structs, enums, and tuples | ||
* Calls to other `const fn`s | ||
* Index expressions on arrays and slices | ||
* Field accesses on structs and tuples | ||
* Reading from constants (but not statics, not even taking a reference to a static) | ||
* `&` and `*` of references | ||
* Casts, except for raw pointer to integer casts | ||
|
||
We'll be slowly growing the abilities of `const fn`, but we've decided that | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
this is enough useful stuff to start shipping the feature itself. | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
For full details, please see [the | ||
reference](https://doc.rust-lang.org/reference/items/functions.html#const-functions). | ||
|
||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
### Tool lints | ||
|
||
In [Rust 1.30](https://blog.rust-lang.org/2018/10/25/Rust-1.30.0.html), we | ||
stabilized "tool attributes", like `#[rustfmt::skip]`. In Rust 1.31, we're | ||
stabilizing something similar: "tool lints," like | ||
`#[allow(clippy::something)]` These give a namespace to lints, so that it's | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
more clear which tool they're coming from. | ||
|
||
If you previously used Clippy's lints, you can migrate like this: | ||
|
||
```rust | ||
// old | ||
#![allow(bool_comparison)] | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// new | ||
#![allow(clippy::bool_comparison)] | ||
``` | ||
|
||
You'll get warnings that can help you update to the new style. | ||
|
||
### Library stabilizations | ||
|
||
A bunch of `From` implementations have been added: | ||
|
||
* `u8` now implements `From<NonZeroU8>`, and likewise for the other numeric types and their `NonZero` equivalents | ||
* `Option<&T>` implements `From<&Option<T>>`, and likewise for `&mut` | ||
|
||
Additionally, these functions have been stabilized: | ||
|
||
* [`slice::align_to`](https://doc.rust-lang.org/std/primitive.slice.html#method.align_to) and its mutable counterpart | ||
* [`slice::chunks_exact`](https://doc.rust-lang.org/std/primitive.slice.html#method.chunks_exact), | ||
as well as its mutable and `r` counterparts (like | ||
[`slice::rchunks_exact_mut`](https://doc.rust-lang.org/std/primitive.slice.html#method.rchunks_mut)) in all combinations | ||
|
||
See the [detailed release notes][notes] for more. | ||
|
||
### Cargo features | ||
|
||
Cargo will now download packages in parallel using HTTP/2. Additionally, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should state how much quicker this is, will follow up... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Up to 20x faster" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have these numbers? how reliable are they? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we have the detail. But I think they are reliable (the number is from a GH issue, so it must be true). |
||
now that `extern crate` is gone, you can't `extern crate foo as bar;` anymore | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
to rename a crate. As such, you can do so in your `Cargo.toml`, like this: | ||
|
||
```toml | ||
[dependencies] | ||
baz = { version = "0.1", package = "foo" } | ||
``` | ||
|
||
or, the equivalent | ||
|
||
```toml | ||
[dependencies.baz] | ||
version = "0.1" | ||
package = "foo" | ||
``` | ||
|
||
Now, the `baz` package will be able to be used via `foo` in your code. | ||
steveklabnik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
See the [detailed release notes][notes] for more. | ||
|
||
## Contributors to 1.31.0 | ||
|
||
Many people came together to create Rust 1.31. We couldn't have done it | ||
without all of you. [Thanks!](https://thanks.rust-lang.org/rust/1.31.0) |
Uh oh!
There was an error while loading. Please reload this page.