Skip to content

Commit

Permalink
add post about the release of rust 1.41.0
Browse files Browse the repository at this point in the history
  • Loading branch information
pietroalbini committed Jan 30, 2020
1 parent b06f8d5 commit 172599d
Showing 1 changed file with 211 additions and 0 deletions.
211 changes: 211 additions & 0 deletions posts/2020-01-30-Rust-1.41.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
---
layout: post
title: "Announcing Rust 1.41.0"
author: The Rust Release Team
release: true
---

The Rust team is happy to announce a new version of Rust, 1.41.0. Rust is a
programming language that is empowering everyone to build reliable and
efficient software.

If you have a previous version of Rust installed via rustup, getting Rust
1.41.0 is as easy as:

```console
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.41.0][notes] on GitHub.

[install]: https://www.rust-lang.org/install.html
[notes]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1410-2020-01-30

## What's in 1.41.0 stable

The highlights of Rust 1.41.0 include relaxed restrictions for trait
implementations, improvements to `cargo install`, a more `git`-friendly
`Cargo.lock`, and new FFI-related guarantees for `Box<T>`. See the [detailed
release notes][notes] to learn about other changes not covered by this post.

### Relaxed restrictions when implementing traits

[book_orphan]: https://doc.rust-lang.org/book/ch10-02-traits.html#implementing-a-trait-on-a-type
[ref_orphan]: https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence
[book_newtype]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#using-the-newtype-pattern-to-implement-external-traits-on-external-types
[report_orphan]: https://github.com/rust-lang/rust/issues/63599
[rfc_orphan]: https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html

To prevent breakages in the ecosystem when a dependency adds a new trait
`impl`, Rust enforces the [*orphan rule*][book_orphan]. The gist of it is that
a trait `impl` is only allowed if either the trait or the type being
implemented is *local* to (defined in) the current crate as opposed to a
*foreign* crate. [What this means exactly][ref_orphan] is complicated, however,
when generics are involved.

Before Rust 1.41.0, the orphan rule was unnecessarily strict, getting in the
way of composition. As an example, suppose your crate defines the
`BetterVec<T>` struct, and you want a way to convert your struct to the
standard library's `Vec<T>`. The code you would write is:

```rust
impl<T> From<BetterVec<T>> for Vec<T> {
// ...
}
```

...which is an instance of the pattern:

```rust
impl<T> ForeignTrait<LocalType> for ForeignType<T> {
// ...
}
```

In Rust 1.40.0 this `impl` was forbidden by the orphan rule, as both `From` and
`Vec` are defined in the standard library, which is foreign to the current
crate. There were ways to work around the limitation, such as [the *newtype*
pattern][book_newtype], but they were often cumbersome or even impossible in
some cases.

While it's still true that both `From` and `Vec` were foreign, the trait (in
this case `From`) was parameterized by a local type. Therefore, Rust 1.41.0
allows this `impl`.

For more details, read the [the stabilization report][report_orphan] and [the
RFC proposing the change][rfc_orphan].

### `cargo install` updates packages when outdated

With `cargo install`, you can install binary crates in your system. The command
is often used by the community to install popular CLI tools written in Rust.

Starting from Rust 1.41.0, `cargo install` will also update existing
installations of the crate if a new release came out since you installed it.
Before this release the only option was to pass the `--force` flag, which
reinstalls the binary crate even if it's up to date.

### Less conflict-prone `Cargo.lock` format

To ensure consistent builds, Cargo uses a file named `Cargo.lock`, containing
dependency versions and checksums. Unfortunately, the way the data was arranged
in it caused unnecessary merge conflicts when changing dependencies in separate
branches.

Rust 1.41.0 introduces a new format for the file, explicitly designed to avoid
those conflicts. This new format will be used for all new lockfiles, while
existing lockfiles will still rely on the previous format. You can learn about
the choices leading to the new format [in the PR adding it][cargo/7070].

[cargo/7070]: https://github.com/rust-lang/cargo/pull/7070

### More guarantees when using `Box<T>` in FFI

[box_docs]: https://doc.rust-lang.org/std/boxed/index.html

Starting with Rust 1.41.0, we have declared that a `Box<T>`, where `T: Sized`
is now ABI compatible with the C language's pointer (`T*`) types. So if you
have an `extern "C"` Rust function, called from C, your Rust function can now
use `Box<T>`, for some specific `T`, while using `T*` in C for the
corresponding function. As an example, on the C side you may have:

```c
// C header */

// Returns ownership to the caller.
struct Foo* foo_new(void);

// Takes ownership from the caller; no-op when invoked with NULL.
void foo_delete(struct Foo*);
```
...while on the Rust side, you would have:
```rust
#[repr(C)]
pub struct Foo;
#[no_mangle]
pub extern "C" fn foo_new() -> Box<Foo> {
Box::new(Foo)
}
// The possibility of NULL is represented with the `Option<_>`.
#[no_mangle]
pub extern "C" fn foo_delete(_: Option<Box<Foo>>) {}
```

Note however that while `Box<T>` and `T*` have the same representation and ABI,
a `Box<T>` must still be non-null, aligned, and ready for deallocation by the
global allocator. To ensure this, it is best to only use `Box`es originating
from the global allocator.

**Important:** At least at present, you should avoid using `Box<T>` types for
functions that are defined in C but invoked from Rust. In those cases, you
should directly mirror the C types as closely as possible. Using types like
`Box<T>` where the C definition is just using `T*` can lead to undefined
behavior.

To read more, [consult the documentation for `Box<T>`][box_docs].

### Library changes

[`Result::map_or`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or
[`Result::map_or_else`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.map_or_else
[`Option::map_or`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.map_or
[`Option::map_or_else`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.map_or_else
[`std::rc::Weak::weak_count`]: https://doc.rust-lang.org/std/rc/struct.Weak.html#method.weak_count
[`std::rc::Weak::strong_count`]: https://doc.rust-lang.org/std/rc/struct.Weak.html#method.strong_count
[`std::sync::Weak::weak_count`]: https://doc.rust-lang.org/std/sync/struct.Weak.html#method.weak_count
[`std::sync::Weak::strong_count`]: https://doc.rust-lang.org/std/sync/struct.Weak.html#method.strong_count
[pr_66277]: https://github.com/rust-lang/rust/pull/66277
[pr_65013]: https://github.com/rust-lang/rust/pull/65013

In Rust 1.41.0, we've made the following additions to the standard library:

- The [`Result::map_or`] and [`Result::map_or_else`] methods were stabilized.

Similar to [`Option::map_or`] and [`Option::map_or_else`], these methods are
shorthands for the `.map(|val| process(val)).unwrap_or(default)` pattern.

- [`NonZero*` numerics now implement `From<NonZero*>` if it's a smaller integer
width.][pr_66277] For example, `NonZeroU16` now implements `From<NonZeroU8>`.

- The `weak_count` and `strong_count` methods were stabilized.

- [`std::rc::Weak::weak_count`]
- [`std::rc::Weak::strong_count`]
- [`std::sync::Weak::weak_count`]
- [`std::sync::Weak::strong_count`]

These methods return the number of weak (`rc::Weak<T>` and `sync::Weak<T>`)
or strong (`Rc<T>` and `Arc<T>`) pointers to the allocation respectively.

- [`MaybeUninit<T>` now implements `fmt::Debug`.][pr_65013]

### Reducing support for 32-bit Apple targets soon

Rust 1.41.0 is the last release with the current level of compiler support for
32-bit Apple targets, including the `i686-apple-darwin` target. Starting from
Rust 1.42.0, these targets will be demoted to the lowest support tier.

[You can learn more about this change in this blog post.][32bit-demotion]

[32bit-demotion]: https://blog.rust-lang.org/2020/01/03/reducing-support-for-32-bit-apple-targets.html

### Other changes

[relnotes-cargo]: https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-141-2020-01-30
[relnotes-clippy]: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-141

There are other changes in the Rust 1.41.0 release: check out what changed in
[Rust][notes], [Cargo][relnotes-cargo], and [Clippy][relnotes-clippy]. We also
have started landing MIR optimizations, which should improve compile times. For
more, read [mir-opt].

## Contributors to 1.41.0

Many people came together to create Rust 1.41.0. We couldn't have done it
without all of you. [Thanks!](https://thanks.rust-lang.org/rust/1.41.0/)

0 comments on commit 172599d

Please sign in to comment.