Skip to content

Commit 13d43cb

Browse files
authored
Merge pull request #257 from rust-lang/1.27-announcement
Rust 1.27
2 parents 54d1c27 + a00e380 commit 13d43cb

File tree

1 file changed

+314
-0
lines changed

1 file changed

+314
-0
lines changed

_posts/2018-06-21-Rust-1.27.md

+314
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
1+
---
2+
layout: post
3+
title: "Announcing Rust 1.27"
4+
author: The Rust Core Team
5+
---
6+
7+
The Rust team is happy to announce a new version of Rust, 1.27.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 via rustup, getting Rust
11+
1.27.0 is as easy as:
12+
13+
```bash
14+
$ rustup update stable
15+
```
16+
17+
If you don't have it already, you can [get `rustup`][install] from the
18+
appropriate page on our website, and check out the [detailed release notes for
19+
1.27.0][notes] on GitHub.
20+
21+
[install]: https://www.rust-lang.org/install.html
22+
[notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1270-2018-06-21
23+
24+
Additionally, we would like to draw attention to something: just before the
25+
release of 1.27.0, we found [a
26+
bug](https://github.com/rust-lang/rust/pull/51686) in the 'default match
27+
bindings' feature introduced in 1.26.0 that can possibly introduce unsoundness.
28+
Since it was discovered very late in the release process, and has been present
29+
since 1.26.0, we decided to stick to our release train model. We expect to put
30+
out a 1.27.1 with that fix applied soon, and if there's demand, possibly a
31+
1.26.3 as well. More information about the specifics here will come in that
32+
release announcement.
33+
34+
## What's in 1.27.0 stable
35+
36+
This release has two big language features that people have been waiting for.
37+
But first, a small comment on documentation: All books in [the Rust
38+
Bookshelf] are [now searchable]! For example, here's [a search of "The Rust
39+
Programming Language" for
40+
'borrow'](https://doc.rust-lang.org/book/second-edition/?search=borrow).
41+
This will hopefully make it much easier to find what you're looking for.
42+
Additionally, there's one new book: [the `rustc` Book]. This book explains
43+
how to use `rustc` directly, as well as some other useful information, like a
44+
list of all lints.
45+
46+
[the Rust Bookshelf]: https://doc.rust-lang.org/
47+
[now searchable]: https://github.com/rust-lang/rust/pull/49623/
48+
[the `rustc` Book]: https://github.com/rust-lang/rust/pull/49707/
49+
50+
### SIMD
51+
52+
Okay, now for the big news: the [basics of SIMD] are now available! SIMD
53+
stands for "single instruction, multiple data." Consider a function
54+
like this:
55+
56+
```rust
57+
pub fn foo(a: &[u8], b: &[u8], c: &mut [u8]) {
58+
for ((a, b), c) in a.iter().zip(b).zip(c) {
59+
*c = *a + *b;
60+
}
61+
}
62+
```
63+
64+
[basics of SIMD]: https://github.com/rust-lang/rust/pull/49664/
65+
66+
Here, we're taking two slices, and adding the numbers together, placing the
67+
result in a third slice. The simplest possible way to do this would be to do
68+
exactly what the code does, and loop through each set of elements, add them
69+
together, and store it in the result. However, compilers can often do better.
70+
LLVM will often "autovectorize" code like this, which is a fancy term for
71+
"use SIMD." Imagine that `a` and `b` were both 16 elements long. Each element
72+
is a `u8`, and so that means that each slice would be 128 bits of data. Using
73+
SIMD, we could put *both* `a` and `b` into 128 bit registers, add them
74+
together in a `*single*` instruction, and then copy the resulting 128 bits
75+
into `c`. That'd be much faster!
76+
77+
While stable Rust has always been able to take advantage of
78+
autovectorization, sometimes, the compiler just isn't smart enough to realize
79+
that we can do something like this. Additionally, not every CPU has these
80+
features, and so LLVM may not use them so your program can be used on a wide
81+
variety of hardware. So, in Rust 1.27, the addtion of [the `std::arch`
82+
module] allows us to use these kinds of instructions *directly*, which
83+
means we don't need to rely on a smart compiler. Additionally, it includes
84+
some features that allow us to choose a particular implementation based
85+
on various criteria. For example:
86+
87+
[the `std::arch` module]: https://doc.rust-lang.org/stable/std/arch/
88+
89+
```rust
90+
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"),
91+
target_feature = "avx2"))]
92+
fn foo() {
93+
#[cfg(target_arch = "x86")]
94+
use std::arch::x86::_mm256_add_epi64;
95+
#[cfg(target_arch = "x86_64")]
96+
use std::arch::x86_64::_mm256_add_epi64;
97+
98+
unsafe {
99+
_mm256_add_epi64(...);
100+
}
101+
}
102+
```
103+
104+
Here, we use `cfg` flags to choose the correct version based on the machine
105+
we're targetting; on `x86` we use that version, and on `x86_64` we use
106+
its version. We can also choose at runtime:
107+
108+
```rust
109+
fn foo() {
110+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
111+
{
112+
if is_x86_feature_detected!("avx2") {
113+
return unsafe { foo_avx2() };
114+
}
115+
}
116+
117+
foo_fallback();
118+
}
119+
```
120+
121+
Here, we have two versions of the function: one which uses `AVX2`, a specific
122+
kind of SIMD feature that lets you do 256-bit operations. The
123+
`is_x86_feature_detected!` macro will generate code that detects if your CPU
124+
supports AVX2, and if so, calls the `foo_avx2` function. If not, then we fall
125+
back to a non-AVX implementation, `foo_fallback`. This means that our code
126+
will run super fast on CPUs that support AVX2, but still work on ones that
127+
don't, albeit slower.
128+
129+
If all of this seems a bit low-level and fiddly, well, it is! `std::arch` is
130+
specifically *primitives* for building these kinds of things. We hope to
131+
eventually stabilize a `std::simd` module with higher-level stuff in the
132+
future. But landing the basics now lets the ecosystem experiment with higher
133+
level libraries starting today. For example, check out the
134+
[faster](https://github.com/AdamNiederer/faster) crate. Here's a code
135+
snippet with no SIMD:
136+
137+
```rust
138+
let lots_of_3s = (&[-123.456f32; 128][..]).iter()
139+
.map(|v| {
140+
9.0 * v.abs().sqrt().sqrt().recip().ceil().sqrt() - 4.0 - 2.0
141+
})
142+
.collect::<Vec<f32>>();
143+
```
144+
145+
To use SIMD with this code via `faster`, you'd change it to this:
146+
147+
```rust
148+
let lots_of_3s = (&[-123.456f32; 128][..]).simd_iter()
149+
.simd_map(f32s(0.0), |v| {
150+
f32s(9.0) * v.abs().sqrt().rsqrt().ceil().sqrt() - f32s(4.0) - f32s(2.0)
151+
})
152+
.scalar_collect();
153+
```
154+
155+
It looks almost the same: `simd_iter` instead of `iter`, `simd_map` instead
156+
of `map`, `f32s(2.0)` instead of `2.0`. But you get a SIMD-ified version
157+
generated for you.
158+
159+
Beyond *that*, you may never write any of this yourself, but as always, the
160+
libraries you depend on may. For example, the [regex crate has already added
161+
support](https://github.com/rust-lang/regex/pull/456), and a new release
162+
will contain these SIMD speedups without you needing to do anything at all!
163+
164+
### `dyn Trait`
165+
166+
Rust's trait object syntax is one that we ultimately regret. If you'll recall,
167+
given a trait `Foo`, this is a trait object:
168+
169+
```rust
170+
Box<Foo>
171+
```
172+
173+
However, if `Foo` were a struct, it'd just be a normal struct placed inside a
174+
`Box<T>`. When designing the language, we though that the similarity here was
175+
a good thing, but experience has demonstrated that it is confusing. And it's
176+
not just for the `Box<Trait>` case; `impl SomeTrait for SomeOtherTrait` is
177+
also technically valid syntax, but you almost always want to write `impl<T>
178+
SomeTrait for T where T: SomeOtherTrait` instead. Same with `impl SomeTrait`,
179+
which looks like it would add methods or possibly default implementations
180+
but in fact adds inherent methods to a trait object. Finally, with the recent
181+
addition of `impl Trait` syntax, it's `impl Trait` vs `Trait` when explaining
182+
things, and so that feels like `Trait` is what you should use, given that it's
183+
shorter, but in reality, that's not always true.
184+
185+
As such, in Rust 1.27, we have stabilized a new syntax, [`dyn Trait`]. A
186+
trait object now looks like this:
187+
188+
```rust
189+
// old => new
190+
Box<Foo> => Box<dyn Foo>
191+
&Foo => &dyn Foo
192+
&mut Foo => &mut dyn Foo
193+
```
194+
195+
And similarly for other pointer types, `Arc<Foo>` is now `Arc<dyn Foo>`, etc.
196+
Due to backwards compatibility, we cannot remove the old syntax, but we have
197+
included a lint, which is set to allow by default, called [`bare-trait-object`].
198+
If you want to lint against the older syntax, you can turn it on. We thought that
199+
it would throw far too many warnings to turn on by default at present.
200+
201+
> Incidentally, we're working on a tool called `rustfix` that can automatically
202+
> upgrade your code to newer idioms. It uses these sorts of lints to do so.
203+
> Expect to hear more about `rustfix` in a future announcement.
204+
205+
[`dyn Trait`]: https://github.com/rust-lang/rfcs/blob/master/text/2113-dyn-trait-syntax.md
206+
[`bare-trait-object`]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#bare-trait-object
207+
208+
### `#[must_use]` on functions
209+
210+
Finally, the `#[must_use]` attribute is getting an upgrade: [it can now be
211+
used on functions](https://github.com/rust-lang/rust/pull/48925/).
212+
213+
Previously, it only applied to types, like `Result<T, E>`. But now, you can
214+
do this:
215+
216+
```rust
217+
#[must_use]
218+
fn double(x: i32) -> i32 {
219+
2 * x
220+
}
221+
222+
fn main() {
223+
double(4); // warning: unused return value of `double` which must be used
224+
225+
let _ = double(4); // (no warning)
226+
}
227+
```
228+
229+
We've also [enhanced several bits of the standard
230+
library](https://github.com/rust-lang/rust/pull/49533/) to make use of this;
231+
`Clone::clone`, `Iterator::collect`, and `ToOwned::to_owned` will all start
232+
warning if you don't use their results, helping you notice expensive operations
233+
you may be throwing away by accident.
234+
235+
See the [detailed release notes][notes] for more.
236+
237+
### Library stabilizations
238+
239+
Several new APIs were stabilized this release:
240+
241+
- [`DoubleEndedIterator::rfind`]
242+
- [`DoubleEndedIterator::rfold`]
243+
- [`DoubleEndedIterator::try_rfold`]
244+
- [`Duration::from_micros`]
245+
- [`Duration::from_nanos`]
246+
- [`Duration::subsec_micros`]
247+
- [`Duration::subsec_millis`]
248+
- [`HashMap::remove_entry`]
249+
- [`Iterator::try_fold`]
250+
- [`Iterator::try_for_each`]
251+
- [`NonNull::cast`]
252+
- [`Option::filter`]
253+
- [`String::replace_range`]
254+
- [`Take::set_limit`]
255+
- [`hint::unreachable_unchecked`]
256+
- [`os::unix::process::parent_id`]
257+
- [`process::id`]
258+
- [`ptr::swap_nonoverlapping`]
259+
- [`slice::rsplit_mut`]
260+
- [`slice::rsplit`]
261+
- [`slice::swap_with_slice`]
262+
263+
[`DoubleEndedIterator::rfind`]: https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html#method.rfind
264+
[`DoubleEndedIterator::rfold`]: https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html#method.rfold
265+
[`DoubleEndedIterator::try_rfold`]: https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html#method.try_rfold
266+
[`Duration::from_micros`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_micros
267+
[`Duration::from_nanos`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.from_nanos
268+
[`Duration::subsec_micros`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.subsec_micros
269+
[`Duration::subsec_millis`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.subsec_millis
270+
[`HashMap::remove_entry`]: https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.remove_entry
271+
[`Iterator::try_fold`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.try_fold
272+
[`Iterator::try_for_each`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.try_for_each
273+
[`NonNull::cast`]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.cast
274+
[`Option::filter`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.filter
275+
[`String::replace_range`]: https://doc.rust-lang.org/std/string/struct.String.html#method.replace_range
276+
[`Take::set_limit`]: https://doc.rust-lang.org/std/io/struct.Take.html#method.set_limit
277+
[`slice::rsplit_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rsplit_mut
278+
[`slice::rsplit`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rsplit
279+
[`slice::swap_with_slice`]: https://doc.rust-lang.org/std/primitive.slice.html#method.swap_with_slice
280+
[`hint::unreachable_unchecked`]: https://doc.rust-lang.org/std/hint/fn.unreachable_unchecked.html
281+
[`os::unix::process::parent_id`]: https://doc.rust-lang.org/std/os/unix/process/fn.parent_id.html
282+
[`ptr::swap_nonoverlapping`]: https://doc.rust-lang.org/std/ptr/fn.swap_nonoverlapping.html
283+
[`process::id`]: https://doc.rust-lang.org/std/process/fn.id.html
284+
285+
See the [detailed release notes][notes] for more.
286+
287+
### Cargo features
288+
289+
Cargo has two small upgrades this release. First, it now [takes a
290+
`--target-dir` flag](https://github.com/rust-lang/cargo/pull/5393/) if you'd
291+
like to change the target directory for a given invocation.
292+
293+
Additionally, a tweak to the way Cargo deals with targets has landed. Cargo
294+
will attempt to automatically discover tests, examples, and binaries within
295+
your project. However, sometimes explicit configuration is needed. But the
296+
initial implementation had a problem: let's say that you have two examples,
297+
and Cargo is discovering them both. You want to tweak one of them, and so
298+
you add a `[[example]]` to your `Cargo.toml` to configure its settings.
299+
Cargo currently sees that you've set one explicitly, and therefore, doesn't
300+
attempt to do any autodetection for the others. That's quite surprising.
301+
302+
As such, we've [added several 'auto' keys to
303+
`Cargo.toml`](https://github.com/rust-lang/cargo/pull/5335/) We can't fix
304+
this behavior without possibly breaking projects that may have inadvertently
305+
been relying on it, and so, if you'd like to configure some targets, but not
306+
others, you can set the `autoexamples` key to `true` in the `[package]`
307+
section.
308+
309+
See the [detailed release notes][notes] for more.
310+
311+
## Contributors to 1.27.0
312+
313+
Many people came together to create Rust 1.27. We couldn't have done it
314+
without all of you. [Thanks!](https://thanks.rust-lang.org/rust/1.27.0)

0 commit comments

Comments
 (0)