Rust 1.32 release

Original author: The Rust Release Team
  • Transfer

The Rust development team is pleased to announce the release of a new version of Rust, 1.32.0. Rust is a programming language that allows everyone to create reliable and effective software.


If you have installed the previous version of Rust with rustup, then to update Rust to version 1.32.0 you just need to run:


$ rustup update stable

If you have not installed it yet rustup, you can install it from the corresponding page of our website. With the detailed release notes Rust 1.32.0 is available on GitHub.


A quick note: there have been several new releases lately rustup! To upgrade yourself rustup, follow rustup self update.

What is included in the stable version 1.32.0


Rust 1.32.0 acquired several life-enhancing improvements, changed the default memory allocator and made more functions constant. Read about these changes below or see the release notes for details .


Macro dbg


Let's start with a life-enhancing improvement. Are you using "print debugging"? If yes, and you want to print some value in the process of working on the code, you are forced to do this:


let x = 5;
println!("{:?}", x);
// или даже такprintln!("{:#?}", x);

This is not the biggest obstacle that slows down development, but it takes too much effort for simple debug output x. In addition, the context is not taken into account. If you have several such things println!, it becomes difficult to determine what is related to the output, until you add context information to each call yourself, which requires even more work.


For these purposes, in Rust 1.32.0 we added a new dbg macro! :


fnmain() {
    let x = 5;
    dbg!(x);
}

After starting this program, you will see:


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

Together with the variable name and its value, the file name and the line number where the call was made will be displayed dbg!.


In addition, it println!prints to standard output, so it’s best to use eprintln!for printing to standard error. Macro dbg!output to stderr, and rightly so.


It works even in difficult cases. Consider an example of factorial implementation:


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

In order to debug it, we can use eprintln!:


fnfactorial(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 output nat each iteration and see the context of each of the branches. For factorial(4)will be displayed:


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

This is acceptable, but not particularly good. Perhaps we could work on improving the display of context information to make the conclusion clearer. But then, instead of debugging your code, we will be working on improving the debugging code.


Consider the same example using dbg!:


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

We simply wrapped a macro with each of the expressions we want to output. As a result, we get:


[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

Since the macro dbg!returns the debugged value itself, unlike the eprintln!one that returns (), we do not need to make any changes in the structure of our code. Additionally, we get a much more useful conclusion.


We paid a lot of attention to such a small macro, since we hope that it will simplify your debugging process. Of course, we also continue to work on support gdband co.


Removed by default jemalloc


A long time ago, Rust had a big runtime, similar to Erlang. For him, jemalloc was chosen instead of the system allocator, because it was often more productive. Gradually, we got rid of the runtime more and more, and in the end it was almost all removed, but the jemalloc remained. We had no way to choose a user allocator, and therefore we could not completely remove jemalloc so as not to harm those who needed it.


In addition, the claim that it jemallocwas always the default allocator pertained predominantly to the UNIX world, since it was by default only on some platforms. In particular, the goal of MSVC on Windows has long been using the system allocator.


Finally, although jemalloc usually has good performance, this is not always the case. In addition, it adds about 300 kilobytes to each executable file. We also have many other problems with jemalloc. And in general, it is strange that the system language does not use the system allocator by default.


For these reasons, as soon as Rust 1.28 provided a way to choose a global allocator , we began to plan the transition to the default system allocator and provision jemallocas an external library. In Rust 1.32, we have finally completed this work, and now by default your program will use the system allocator.


If you want to continue using jemalloc, use the jemallocator library . To do this, Cargo.tomlspecify:


jemallocator = "0.1.8"

And in the root file of your project:


#[global_allocator]static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

That's all! If you do not need jemalloc, you are no longer forced to use it, but if you need it, then the problem is solved with a few lines of code.


Final module system improvements


In the last two issues, we talked about several improvements to the module system. In 1.32.0 and edition 2018, we added the last change. It is called "uniform paths" and allows you to work with import paths in the same way as with other paths, which previously did not work correctly. For example:


enumColor { Red, Green, Blue }
use Color::*;

This code has not been compiled before , because the paths in usemust have started with super, selfor crate. Now, thanks to the compiler support for uniform paths, this code will work and do what you expect: importing the options defined in the above listing Color.


This change completes our revision of the module system. We hope you enjoy working with the simplified system!


Macro enhancements


Rust 1.32.0 released several macro enhancements. First, a new literal fragment specifier was added :


macro_rules! m {
    ($lt:literal) => {};
}
fnmain() {
    m!("some string literal");
}

The fragment is literalcompared to literals of any type: string, numeric, and character.


In the 2018 edition, macro_rulesyou can also use in the macro ?:


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

Fragment c ?will be matched with zero or one occurrence, just as a fragment with *already matched "zero or more" occurrences, and c +- "one or more" occurrences.


Standard Library Stabilization


The macro dbg!, which we have already described above, has become an important addition to the standard library. In addition, 19 functions were made constant, and all numerical primitive types received conversion functions into a byte array and back with the specified byte order. A total of six functions with names to_<endian>_bytesand from_<endian>_byteswhere <endian>it is:


  • ne - native order (native endianness)
  • le - order from junior to senior (little endian)
  • be - order from senior to junior (big endian)

See the release notes for details .


Improvements in Cargo


Cargo has been given the cargo c alias for the cargo check team , and now allows the use of usernames in repository URLs .


See the release notes for details .


Developers 1.32.0


Many people co-created Rust 1.32.0. We could not complete the work without the participation of each of you. Thank!


From the translator: I express special thanks to the members of the Rustycrate community and personally @dashadee and ozkriff for their help with translation and proofreading.


Also popular now: