Skip to content

Changes for Rust 1.32 & setup for edition-next #213

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

Merged
merged 6 commits into from
May 18, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -85,3 +85,13 @@
- [MSVC toolchain support](rust-2018/platform-and-target-support/msvc-toolchain-support.md)
- [MUSL support for fully static binaries](rust-2018/platform-and-target-support/musl-support-for-fully-static-binaries.md)
- [`cdylib` crates for C interoperability](rust-2018/platform-and-target-support/cdylib-crates-for-c-interoperability.md)

## The Next Edition

- [The Next Edition](rust-next/index.md)
- [Next-Specific Changes](rust-next/edition-changes.md)
- [The dbg! macro](rust-next/dbg-macro.md)
- [No jemalloc by default](rust-next/no-jemalloc.md)
- [Uniform Paths](rust-next/uniform-paths.md)
- [`literal` macro matcher](rust-next/literal-macro-matcher.md)
- [`?` operator in macros](rust-next/qustion-mark-operator-in-macros.md)
104 changes: 104 additions & 0 deletions src/rust-next/dbg-macro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# The dbg! macro

![Minimum Rust version: 1.32](https://img.shields.io/badge/Minimum%20Rust%20Version-1.32-brightgreen.svg)

The `dbg!` macro provides a nicer experience for debugging than `println!`:

```rust
fn main() {
let x = 5;

dbg!(x);
}
```

If you run this program, you'll see:

```text
[src/main.rs:4] x = 5
```

You get the file and line number of where this was invoked, as well as the
name and value. Additionally, `println!` prints to the standard output, so you
really should be using `eprintln!` to print to standard error. `dbg!` does the
right thing and goes to stderr.

It even works in more complex circumstances. Consider this factorial example:

```rust
fn factorial(n: u32) -> u32 {
if n <= 1 {
n
} else {
n * factorial(n - 1)
}
}
```

If we wanted to debug this, we might write it like this with `eprintln!`:

```rust
fn factorial(n: u32) -> u32 {
eprintln!("n: {}", n);

if n <= 1 {
eprintln!("n <= 1");

n
} else {
let n = n * factorial(n - 1);

eprintln!("n: {}", n);

n
}
}
```

We want to log `n` on each iteration, as well as have some kind of context
for each of the branches. We see this output for `factorial(4)`:

```text
n: 4
n: 3
n: 2
n: 1
n <= 1
n: 2
n: 6
n: 24
```

This is servicable, but not particularly great. Maybe we could work on how we
print out the context to make it more clear, but now we're not debugging our
code, we're figuring out how to make our debugging code better.

Consider this version using `dbg!`:

```rust
fn factorial(n: u32) -> u32 {
if dbg!(n <= 1) {
dbg!(1)
} else {
dbg!(n * factorial(n - 1))
}
}
```

We simply wrap each of the various expressions we want to print with the macro. We get this output instead:

```text
[src/main.rs:3] n <= 1 = false
[src/main.rs:3] n <= 1 = false
[src/main.rs:3] n <= 1 = false
[src/main.rs:3] n <= 1 = true
[src/main.rs:4] 1 = 1
[src/main.rs:5] n * factorial(n - 1) = 2
[src/main.rs:5] n * factorial(n - 1) = 6
[src/main.rs:5] n * factorial(n - 1) = 24
[src/main.rs:11] factorial(4) = 24
```

Because the `dbg!` macro returns the value of what it's debugging, instead of
`eprintln!` which returns `()`, we need to make no changes to the structure of
our code. Additionally, we have vastly more useful output.
3 changes: 3 additions & 0 deletions src/rust-next/edition-changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Next-Specific Changes

There have been no specific changes accepted for the next edition yet.
7 changes: 7 additions & 0 deletions src/rust-next/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# The Next Edition

We have not decided if and when the next edition will ship; there is talk of
a 2021 edition to keep up the three-year schedule, but that has not been
formally decided.

Until we do, this section keeps track of changes that landed after Rust 2018.
18 changes: 18 additions & 0 deletions src/rust-next/literal-macro-matcher.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# literal macro matcher

![Minimum Rust version: 1.32](https://img.shields.io/badge/Minimum%20Rust%20Version-1.32-brightgreen.svg)

A new `literal` matcher was added for macros:

```rust
macro_rules! m {
($lt:literal) => {};
}

fn main() {
m!("some string literal");
}
```

`literal` matches against literals of any type; string literals, numeric
literals, `char` literals.
43 changes: 43 additions & 0 deletions src/rust-next/no-jemalloc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# No jemalloc by default

![Minimum Rust version: 1.32](https://img.shields.io/badge/Minimum%20Rust%20Version-1.32-brightgreen.svg)

Long, long ago, Rust had a large, Erlang-like runtime. We chose to use
jemalloc instead of the system allocator, because it often improved
performance over the default system one. Over time, we shed more and more of
this runtime, and eventually almost all of it was removed, but jemalloc was
not. We didn't have a way to choose a custom allocator, and so we couldn't
really remove it without causing a regression for people who do need
jemalloc.

Also, saying that jemalloc was always the default is a bit UNIX-centric, as
it was only the default on some platforms. Notably, the MSVC target on
Windows has shipped the system allocator for a long time.

While jemalloc usually has great performance, that's not always the case.
Additionally, it adds about 300kb to every Rust binary. We've also had a host
of other issues with jemalloc in the past. It has also felt a little strange
that a systems language does not default to the system's allocator.

For all of these reasons, once Rust 1.28 shipped a way to choose a global
allocator, we started making plans to switch the default to the system
allocator, and allow you to use jemalloc via a crate. In Rust 1.32, we've
finally finished this work, and by default, you will get the system allocator
for your programs.

If you'd like to continue to use jemalloc, use the jemallocator crate. In
your Cargo.toml:

```toml
jemallocator = "0.1.8"
```

And in your crate root:

```rust,ignore
#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
```

That's it! If you don't need jemalloc, it's not forced upon you, and if you
do need it, it's a few lines of code away.
14 changes: 14 additions & 0 deletions src/rust-next/qustion-mark-operator-in-macros.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# ? operator in macros

![Minimum Rust version: 1.32](https://img.shields.io/badge/Minimum%20Rust%20Version-1.32-brightgreen.svg)

`macro_rules` macros can use `?`, like this:

```rust
macro_rules! bar {
($(a)?) => {}
}
```

The `?` will match zero or one repetitions of the pattern, similar to the
already-existing `*` for "zero or more" and `+` for "one or more."
23 changes: 23 additions & 0 deletions src/rust-next/uniform-paths.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Uniform Paths

![Minimum Rust version: 1.32](https://img.shields.io/badge/Minimum%20Rust%20Version-1.32-brightgreen.svg)

Rust 2018 added several improvements to the module system. We have one last
tweak landing in 1.32.0. Nicknamed "uniform paths", it permits previously
invalid import path statements to be resolved exactly the same way as
non-import paths. For example:

```rust,edition2018
enum Color {
Red,
Green,
Blue,
}

use Color::*;
```

This code did not previously compile, as use statements had to start with
`super`, `self`, or `crate`. Now that the compiler supports uniform paths,
this code will work, and do what you probably expect: import the variants of
the Color enum defined above the `use` statement.