Skip to content

Commit f31c035

Browse files
authored
Merge pull request #153 from rust-lang/1.16-announcement
Add announcement post for 1.16
2 parents 871c221 + faa8ea8 commit f31c035

File tree

1 file changed

+316
-0
lines changed

1 file changed

+316
-0
lines changed

_posts/2017-03-16-Rust-1.16.md

+316
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
---
2+
layout: post
3+
title: "Announcing Rust 1.16"
4+
author: The Rust Core Team
5+
---
6+
7+
The Rust team is happy to announce the latest version of Rust, 1.16.0. Rust is a
8+
systems programming language focused on safety, speed, and concurrency.
9+
10+
If you have a previous version of Rust installed, getting Rust 1.16 is as easy as:
11+
12+
```bash
13+
$ rustup update stable
14+
```
15+
16+
If you don't have it already, you can [get `rustup`][install] from the
17+
appropriate page on our website, and check out the [detailed release notes for
18+
1.16.0][notes] on GitHub.
19+
20+
[install]: https://www.rust-lang.org/install.html
21+
[notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1160-2017-03-16
22+
23+
### What's in 1.16.0 stable
24+
25+
The largest addition to Rust 1.16 is `cargo check`. This new subcommand should speed up the development
26+
workflow in many cases.
27+
28+
What does it do? Let's take a step back and talk about how `rustc` compiles your code. Compilation has many
29+
"passes", that is, there are many distinct steps that the compiler takes on the road from your source code
30+
to producing the final binary. You can see each of these steps (and how much time and memory they take)
31+
by passing `-Z time-passes` to a nightly compiler:
32+
33+
```text
34+
rustc .\hello.rs -Z time-passes
35+
time: 0.003; rss: 16MB parsing
36+
time: 0.000; rss: 16MB recursion limit
37+
time: 0.000; rss: 16MB crate injection
38+
time: 0.000; rss: 16MB plugin loading
39+
time: 0.000; rss: 16MB plugin registration
40+
time: 0.049; rss: 34MB expansion
41+
<snip>
42+
```
43+
44+
There's a lot of them. However, you can think of this process in two big steps: first, `rustc` does
45+
all of its safety checks, makes sure your syntax is correct, all that stuff. Second, once it's satisfied
46+
that everything is in order, it produces the actual binary code that you end up executing.
47+
48+
It turns out that that second step takes a lot of time. And most of the time, it's not neccesary. That is,
49+
when you're working on some Rust code, many developers will get into a workflow like this:
50+
51+
1. Write some code.
52+
2. Run `cargo build` to make sure it compiles.
53+
3. Repeat 1-2 as needed.
54+
4. Run `cargo test` to make sure your tests pass.
55+
5. GOTO 1.
56+
57+
In step two, you never actually run your code. You're looking for feedback from the compiler, not to
58+
actually run the binary. `cargo check` supports exactly this use-case: it runs all of the compiler's
59+
checks, but doesn't produce the final binary.
60+
61+
So how much speedup do you actually get? Like most performance related questions, the answer is "it
62+
depends." Here are some very un-scientific benchmarks:
63+
64+
| | initial build | initial check | speedup | secondary build | secondary check | speedup |
65+
|--------|---------------|---------------|---------|-----------------|-----------------|---------|
66+
| thanks | 134.75s | 50.88s | 2.648 | 15.97s | 2.9s | 5.506 |
67+
| cargo | 236.78s | 148.52s | 1.594 | 64.34s | 9.29s | 6.925 |
68+
| diesel | 15.27s | 12.81s | 0.015 | 13.54s | 12.3s | 1.100 |
69+
70+
The 'initial' categories are the first build after cloning down a project. The 'secondary' categories
71+
involved adding one blank line to the top of `src\lib.rs` and running the command again. That's why
72+
the initial ones are more dramatic; they involve also doing this for all dependencies, as well as
73+
the crate itself. As you can see, larger projects with many dependencies see a big improvement, but
74+
smaller ones see much more modest gains.
75+
76+
We are still working on improving compile-times generally as well, though we don't have anything
77+
in particular to highlight at this time.
78+
79+
#### Other improvements
80+
81+
To support `cargo check`, `rustc` has [learned to emit] a new kind of file: `.rmeta`. This file
82+
will contain only the metadata about a particular crate. `cargo check` needs this for your
83+
dependencies, to let the compiler check types and such from them. It's also useful for the
84+
[Rust Language Server], and possibly more tools in the future.
85+
86+
[learned to emit]: https://github.com/rust-lang/rust/pull/38571
87+
[Rust Language Server]: https://github.com/rust-lang-nursery/rls
88+
89+
Another large change is the removal of a long-standing diagnostic: `consider using an explicit
90+
lifetime parameter`. This diagnostic would kick in whenever you had an incorrect lifetime annotation,
91+
and the compiler thought that you might have meant something else. Consider this code:
92+
93+
```rust
94+
use std::str::FromStr;
95+
96+
pub struct Name<'a> {
97+
name: &'a str,
98+
}
99+
100+
impl<'a> FromStr for Name<'a> {
101+
type Err = ();
102+
103+
fn from_str(s: &str) -> Result<Name, ()> {
104+
Ok(Name { name: s })
105+
}
106+
}
107+
```
108+
109+
Here, Rust isn't sure what to do with the lifetimes; as written, the code doesn't guarantee that `s`
110+
will live as long as `Name`, which is required for `Name` to be valid. Let's try to compile this
111+
code with Rust 1.15.1:
112+
113+
```bash
114+
> rustc +1.15.1 foo.rs --crate-type=lib
115+
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
116+
--> .\foo.rs:10:5
117+
|
118+
10 | fn from_str(s: &str) -> Result<Name, ()> {
119+
| _____^ starting here...
120+
11 | | Ok(Name { name: s })
121+
12 | | }
122+
| |_____^ ...ending here
123+
|
124+
help: consider using an explicit lifetime parameter as shown: fn from_str(s: &'a str) -> Result<Name, ()>
125+
--> .\foo.rs:10:5
126+
|
127+
10 | fn from_str(s: &str) -> Result<Name, ()> {
128+
| _____^ starting here...
129+
11 | | Ok(Name { name: s })
130+
12 | | }
131+
| |_____^ ...ending here
132+
```
133+
134+
The compiler explains the issue, and gives a helpful suggestion. So let's try it: modify the code to add in
135+
the `'a`, and compile again:
136+
137+
```bash
138+
> rustc +1.15.1 .\foo.rs --crate-type=lib
139+
error[E0308]: method not compatible with trait
140+
--> .\foo.rs:10:5
141+
|
142+
10 | fn from_str(s: &'a str) -> Result<Name, ()> {
143+
| _____^ starting here...
144+
11 | | Ok(Name { name: s })
145+
12 | | }
146+
| |_____^ ...ending here: lifetime mismatch
147+
|
148+
<snip>
149+
help: consider using an explicit lifetime parameter as shown: fn from_str(s: &'a str) -> Result<Name<'a>, ()>
150+
--> .\foo.rs:10:5
151+
|
152+
10 | fn from_str(s: &'a str) -> Result<Name, ()> {
153+
| _____^ starting here...
154+
11 | | Ok(Name { name: s })
155+
12 | | }
156+
| |_____^ ...ending here
157+
```
158+
159+
It still doesn't work. That help message was not actually helpful. It does suggest adding another
160+
lifetime, this time on `Name`. If we do that...
161+
162+
```bash
163+
> rustc +1.15.1 .\foo.rs --crate-type=lib
164+
<snip>
165+
help: consider using an explicit lifetime parameter as shown: fn from_str(s: &'a str) -> Result<Name<'a>, ()>
166+
--> .\foo.rs:10:5
167+
```
168+
169+
... that's what we already have, compiler!
170+
171+
This diagnostic was well-intentioned, but when it's wrong, it was *very* wrong, as you can see here. Sometimes
172+
it wouldn't even suggest valid Rust syntax! Furthermore, more advanced Rust users didn't really need the
173+
suggestion, but new Rustaceans would take them to heart, and then be led down this bad path. As such, we decided
174+
that for now, [we should remove the help message entirely]. We may bring it back in the future, but only if we can
175+
limit false positives.
176+
177+
[we should remove the help message entirely]: https://github.com/rust-lang/rust/pull/37057
178+
179+
In other diagnostic changes, previous versions of Rust would helpfully attempt to suggest fixes for typos:
180+
181+
```rust
182+
let foo = 5;
183+
184+
println!("{}", ffo);
185+
```
186+
187+
Would give this error:
188+
189+
```text
190+
error[E0425]: cannot find value `ffo` in this scope
191+
--> foo.rs:4:20
192+
|
193+
4 | println!("{}", ffo);
194+
| ^^^ did you mean `foo`?
195+
```
196+
197+
However, this would only happen in certain circumstances: sometimes in local variables, and for fields in
198+
structs. [This now happens nearly everywhere]. When combined with [some other related improvements], this
199+
results in a significant improvement in these sorts of diagnostics.
200+
201+
[This now happens nearly everywhere]: https://github.com/rust-lang/rust/pull/38927
202+
[some other related improvements]: https://github.com/rust-lang/rust/pull/38154
203+
204+
See the [detailed release notes][notes] for more.
205+
206+
#### Library stabilizations
207+
208+
21 new bits of API were stabilized this release:
209+
210+
* [`VecDeque::truncate`]
211+
* [`VecDeque::resize`]
212+
* [`String::insert_str`]
213+
* [`Duration::checked_add`]
214+
* [`Duration::checked_sub`]
215+
* [`Duration::checked_div`]
216+
* [`Duration::checked_mul`]
217+
* [`str::replacen`]
218+
* [`str::repeat`]
219+
* [`SocketAddr::is_ipv4`]
220+
* [`SocketAddr::is_ipv6`]
221+
* [`IpAddr::is_ipv4`]
222+
* [`IpAddr::is_ipv6`]
223+
* [`Vec::dedup_by`]
224+
* [`Vec::dedup_by_key`]
225+
* [`Result::unwrap_or_default`]
226+
* [`<*const T>::wrapping_offset`]
227+
* [`<*mut T>::wrapping_offset`]
228+
* `CommandExt::creation_flags`
229+
* [`File::set_permissions`]
230+
* [`String::split_off`]
231+
232+
[`<*const T>::wrapping_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset
233+
[`<*mut T>::wrapping_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset
234+
[`Duration::checked_add`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_add
235+
[`Duration::checked_div`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_div
236+
[`Duration::checked_mul`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_mul
237+
[`Duration::checked_sub`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_sub
238+
[`File::set_permissions`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.set_permissions
239+
[`IpAddr::is_ipv4`]: https://doc.rust-lang.org/std/net/enum.IpAddr.html#method.is_ipv4
240+
[`IpAddr::is_ipv6`]: https://doc.rust-lang.org/std/net/enum.IpAddr.html#method.is_ipv6
241+
[`Result::unwrap_or_default`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or_default
242+
[`SocketAddr::is_ipv4`]: https://doc.rust-lang.org/std/net/enum.SocketAddr.html#method.is_ipv4
243+
[`SocketAddr::is_ipv6`]: https://doc.rust-lang.org/std/net/enum.SocketAddr.html#method.is_ipv6
244+
[`String::insert_str`]: https://doc.rust-lang.org/std/string/struct.String.html#method.insert_str
245+
[`String::split_off`]: https://doc.rust-lang.org/std/string/struct.String.html#method.split_off
246+
[`Vec::dedup_by_key`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.dedup_by_key
247+
[`Vec::dedup_by`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.dedup_by
248+
[`VecDeque::resize`]: https://doc.rust-lang.org/std/collections/vec_deque/struct.VecDeque.html#method.resize
249+
[`VecDeque::truncate`]: https://doc.rust-lang.org/std/collections/vec_deque/struct.VecDeque.html#method.truncate
250+
[`str::repeat`]: https://doc.rust-lang.org/std/primitive.str.html#method.repeat
251+
[`str::replacen`]: https://doc.rust-lang.org/std/primitive.str.html#method.replacen
252+
253+
In addition, a number of small improvements to existing functions landed. For example [`writeln!` now has
254+
a single-argument form], just like `println!` has. This ends up writing only a newline, but is a nice bit
255+
of symmetry.
256+
257+
[`writeln!` now has a single-argument form]: https://github.com/rust-lang/rust/pull/38469
258+
259+
All structs in the standard library [now implement `Debug`].
260+
261+
[now implement `Debug`]: https://github.com/rust-lang/rust/pull/38006
262+
263+
When slicing a `&str`, [you'll see better errors]. For example, this code:
264+
265+
```rust
266+
&"abcαβγ"[..4]
267+
```
268+
269+
Is incorrect. It generates this error:
270+
271+
```text
272+
thread 'str::test_slice_fail_boundary_1' panicked at 'byte index 4 is not
273+
a char boundary; it is inside 'α' (bytes 3..5) of `abcαβγ`'
274+
```
275+
276+
The part after the `;` is new.
277+
278+
[you'll see better errors]: https://github.com/rust-lang/rust/pull/38066
279+
280+
See the [detailed release notes][notes] for more.
281+
282+
#### Cargo features
283+
284+
In addition to `cargo check`, Cargo and crates.io have some new polish added. For example,
285+
[`cargo build`] and [`cargo doc`] now take a `--all` flag for building and documenting every
286+
crate in your workspace with one command.
287+
288+
[`cargo build`]: https://github.com/rust-lang/cargo/pull/3511
289+
[`cargo doc`]: https://github.com/rust-lang/cargo/pull/3515
290+
291+
Cargo now has a [`--version --verbose` flag], mirroring `rustc`.
292+
293+
[`--version --verbose` flag]: https://github.com/rust-lang/cargo/pull/3604
294+
295+
Crates.io now [can show off your TravisCI or AppVeyor badges] on your crate's page.
296+
297+
[can show off your TravisCI or Appveyor badges]: https://github.com/rust-lang/cargo/pull/3546
298+
299+
In addition, both Cargo and crates.io [understand categories]. Unlike keywords, which are free-form,
300+
categories are curated. In addition, keywords are used for searching, but categories are not. In other
301+
words, categories are intended to assist browsing, and keywords are intended to assist searching.
302+
303+
You can browse crates by category [here](https://crates.io/categories).
304+
305+
[understand categories]: https://github.com/rust-lang/cargo/pull/3301
306+
307+
See the [detailed release notes][notes] for more.
308+
309+
### Contributors to 1.16.0
310+
311+
Last release, we introduced [thanks.rust-lang.org](https://thanks.rust-lang.org).
312+
We have been doing some behind-the-scenes refactoring work to allow for more projects
313+
than only Rust itself; we're hoping to introduce that in the next release.
314+
315+
We had 137 individuals contribute to Rust 1.16.
316+
[Thanks!](https://thanks.rust-lang.org/rust/1.16.0)

0 commit comments

Comments
 (0)