Rust Blog: Posts

Rust Blog

Non-lexical lifetimes (NLL) fully stable

As of Rust 1.63 (releasing next week), the "non-lexical lifetimes" (NLL) work will be enabled by default. NLL is the second iteration of Rust's borrow checker. The RFC actually does quite a nice job of highlighting some of the motivating examples. "But," I hear you saying, "wasn't NLL included in Rust 2018?" And yes, yes it was! But at that time, NLL was only enabled for Rust 2018 code, while Rust 2015 code ran in "migration mode". When in "migration mode," the compiler would run both the old and the new borrow checker and compare the results. This way, we could give warnings for older code that should never have compiled in the first place; we could also limit the impact of any bugs in the new code. Over time, we have limited migration mode to be closer and closer to just running the new-style borrow checker: in the next release, that process completes, and all Rust code will be checked with NLL.

How does removing the old borrow checker affect users?

At this point, we have almost completely merged "migration mode" and "regular mode", so switching to NLL will have very little impact on the user experience. A number of diagnostics changed, mostly for the better -- Jack Huey gives the full details in his blog post.

Credit where credit is due

The work to remove the old borrow checker has been going on for years. It's been a long, tedious, and largely thankless process. We'd like to take a moment to highlight the various people involved and make sure they are recognized for their hard work:

Jack's blog post includes a detailed narrative of all the work involved if you'd like more details! It's a fun read.

Looking forward: what can we expect for the "borrow checker of the future"?

The next frontier for Rust borrow checking is taking the polonius project and moving it from research experiment to production code. Polonius is a next-generation version of the borrow checker that was "spun off" from the main NLL effort in 2018, as we were getting NLL ready to ship in production. Its most important contribution is fixing a known limitation of the borrow checker, demonstrated by the following example:

fn last_or_push<'a>(vec: &'a mut Vec<String>) -> &'a String {
    if let Some(s) = vec.last() { // borrows vec
        // returning s here forces vec to be borrowed
        // for the rest of the function, even though it
        // shouldn't have to be
        return s; 
    }
    
    // Because vec is borrowed, this call to vec.push gives
    // an error!
    vec.push("".to_string()); // ERROR
    vec.last().unwrap()
}

This example doesn't compile today (try it for yourself), though there's not a good reason for that. You can often workaround the problem by editing the code to introduce a redundant if (as shown in this example), but with polonius, it will compile as is. If you'd like to learn more about how polonius (and the existing borrow checker) works1, you can watch my talk from Rust Belt Rust.

  1. Or where the name "polonius" comes from!

Continue Reading…

Rust Blog

Increasing the glibc and Linux kernel requirements

The minimum requirements for Rust toolchains targeting Linux will increase with the Rust 1.64.0 release (slated for September 22nd, 2022). The new minimum requirements are:

  • glibc >= 2.17 (previously glibc >= 2.11)
  • kernel >= 3.2 (previously kernel >= 2.6.32)

These requirements apply both to running the Rust compiler itself (and other Rust tooling like Cargo or Rustup), and to running binaries produced by Rust, if they use the libstd.

If you are not targeting an old long-term-support distribution, or embedded hardware running an old Linux version, this change is unlikely to affect you. Otherwise, read on!

Affected targets

In principle, the new kernel requirements affect all *-linux-* targets, while the glibc requirements affect all *-linux-gnu* targets. In practice, many targets were already requiring newer kernel or glibc versions. The requirements for such targets do not change.

Among targets for which a Rust host toolchain is distributed, the following are affected:

  • i686-unknown-linux-gnu (Tier 1)
  • x86_64-unknown-linux-gnu (Tier 1)
  • x86_64-unknown-linux-musl (Tier 2 with host tools)
  • powerpc-unknown-linux-gnu (Tier 2 with host tools)
  • powerpc64-unknown-linux-gnu (Tier 2 with host tools)
  • s390x-unknown-linux-gnu (Tier 2 with host tools)

The following are not affected, because they already had higher glibc/kernel requirements:

  • aarch64-unknown-linux-gnu (Tier 1)
  • aarch64-unknown-linux-musl (Tier 2 with host tools)
  • arm-unknown-linux-gnueabi (Tier 2 with host tools)
  • arm-unknown-linux-gnueabihf (Tier 2 with host tools)
  • armv7-unknown-linux-gnueabihf (Tier 2 with host tools)
  • mips-unknown-linux-gnueabihf (Tier 2 with host tools)
  • powerpc64le-unknown-linux-gnueabihf (Tier 2 with host tools)
  • riscv64gc-unknown-linux-gnueabihf (Tier 2 with host tools)

For other tier 2 or tier 3 targets, for which no Rust toolchain is distributed, we do not accurately track minimum requirements, and they may or may not be affected by this change.*-linux-musl* targets are only affected by the kernel requirements, not the glibc requirements. Targets which only use libcore and not libstd are unaffected.

A list of supported targets and their requirements can be found on theplatform support page. However, the page is not yet up to date with the changes announced here.

Affected systems

The glibc and kernel versions used for the new baseline requirements are already close to a decade old. As such, this change should only affect users that either target old long-term-support Linux distributions, or embedded hardware running old versions of Linux.

The following Linux distributions are still supported under the new requirements:

  • RHEL 7 (glibc 2.17, kernel 3.10)
  • SLES 12-SP5 (glibc 2.22, kernel 4.12.14)
  • Debian 8 (glibc 2.19, kernel 3.16.7)
  • Ubuntu 14.04 (glibc 2.19, kernel 3.13)

The following distributions are not supported under the new requirements:

  • RHEL 6 (glibc 2.12, kernel 2.6.32)
  • SLES 11-SP4 (glibc 2.11.3, kernel 3.0.101)
  • Debian 6 (glibc 2.11, kernel 2.6.32), Debian 7 (glibc 2.13, kernel 3.2.41)
  • Ubuntu 12.04 (glibc 2.15, kernel 3.2)

Out of the distributions in the second list, only RHEL 6 still has limited vendor support (ELS).

Why increase the requirements?

We want Rust, and binaries produced by Rust, to be as widely usable as possible. At the same time, the Rust project only has limited resources to maintain compatibility with old environments.

There are two parts to the toolchain requirements: The minimum requirements for running the Rust compiler on a host system, and the minimum requirements for cross-compiled binaries.

The minimum requirements for host toolchains affect our build system. Rust CI produces binary artifacts for dozens of different targets. Creating binaries that support old glibc versions requires either building on an operating system with old glibc (for native builds) or using a buildroot with an old glibc version (for cross-compiled builds).

At the same time, Rust relies on LLVM for optimization and code generation, which regularly increases its toolchain requirements. LLVM 16 will require GCC 7.1 or newer (and LLVM 15 supports GCC 5.1 in name only). Creating a build environment that has both a very old glibc and a recent compiler becomes increasingly hard over time. crosstool-ng (which we use for most cross-compilation needs) does not support targeting both glibc 2.11, and using a compiler that satisfies the new LLVM requirements.

The requirements for cross-compiled binaries have a different motivation: They affect which kernel versions need to be supported by libstd. Increasing the kernel requirements allows libstd to use newer syscalls, without having to maintain and test compatibility with kernels that do not support them.

The new baseline requirements were picked as the least common denominator among long-term-support distributions that still have active support. This is currently RHEL 7 with glibc 2.17 and kernel 3.10. The kernel requirement is picked as 3.2 instead, because this is the minimum requirement of glibc itself, and there is little relevant API difference between these versions.

What should I do?

If you or your organization are affected by this change, there are a number of viable options depending on your situation:

  • Upgrade your target system, or raise the minimum requirements of your software, to satisfy the new constraints.
  • If you are running the Rust compiler on an old host, consider cross-compiling from a newer host instead.
  • If you are targeting an old glibc version, consider targeting musl instead.
  • If you are targeting an old kernel version and use libstd, you may be out of luck: In this case you may have to either freeze your current Rust version, or maintain a fork of libstd that supports older kernels.

Continue Reading…

Rust Blog

Announcing Rust 1.62.1

The Rust team has published a new point release of Rust, 1.62.1. 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, you can get 1.62.1 with:

rustup update stable

If you don't have it already, you can get rustupfrom the appropriate page on our website, and check out thedetailed release notes for 1.62.1 on GitHub.

What's in 1.62.1 stable

Rust 1.62.1 addresses a few recent regressions in the compiler and standard library, and also mitigates a CPU vulnerability on Intel SGX.

Contributors to 1.62.1

Many people came together to create Rust 1.62.1. We couldn't have done it without all of you. Thanks!

Continue Reading…

Rust Blog

Changes in the Core Team

We want to say farewell and thanks to a couple of people who are stepping back from the Core Team:

  • Aidan Hobson Sayers is leaving the Core Team and other roles. Joining the Core Team in 2018, he started out on the project with fixing CI issues and has been a member of the Infrastructure Team since its inception (moving through lead and co-lead). Aidan wants to dedicate more time to working with the Rust community and growing Rust usage at his company, and is looking forward to doing so from the other side of the fence.
  • Ashley Williams will be stepping down from the Core Team and other roles. She became a member of the Core Team in 2018 and has had impact on many parts of the project, from leading the Community team, to setting up PagerDuty for Infrastructure and Crates.io, to the Wasm working group, to Increasing Rust’s Reach and Rustbridge, to her instrumental work creating the Rust Foundation and serving as its first Executive Director. Ashley is leaving her role in the project to focus on her newly founded company.

Many thanks to both of them for their contributions and we look forward to seeing their future efforts with Rust!

Continue Reading…

Rust Blog

Announcing Rustup 1.25.1

The rustup working group is announcing the release of rustup version 1.25.1.Rustup is the recommended tool to install Rust, a programming language that is empowering everyone to build reliable and efficient software.

If you have a previous version of rustup installed, getting rustup 1.25.1 is as easy as stopping any programs which may be using Rustup (e.g. closing your IDE) and running:

rustup self update

Rustup will also automatically update itself at the end of a normal toolchain update:

rustup update

If you don't have it already, you can get rustup from the appropriate page on our website.

What's new in rustup 1.25.1

This version of rustup fixes a regression introduced in the previous release (1.25.0), which caused some workflows to fail.

Regression in nested Cargo invocations with different toolchains

When you invoke Rust or Cargo installed by rustup, you're not running them directly. Instead, you run rustup "proxy" binaries, whose job is to detect the right toolchain (parsing the +channel CLI argument or using one of the defaults) and run it.

Running these proxies is not instantaneous though, and for example a cargo build invocation might execute several of them (the initial cargo invocation plus one rustc for every dependency), slowing down the build.

To improve performance, rustup 1.25.0 changed the proxies code to set theRUSTC and RUSTDOC environment variables when missing, which instructed Cargo to skip the proxies and invoke the binaries defined in those variables directly. This provided a performance gain when building crates with lots of dependencies.

Unfortunately this change broke some users of rustup, who did something like:

  • The first Cargo invocation (for example an extension, an alias or an integration test) uses toolchain foo, setting the RUSTC and RUSTDOCenvironment variables pointing to that toolchain.
  • The first invocation calls Cargo again, but this time using toolchain bar(for example cargo +bar build). This does not set the RUSTC andRUSTDOC environment variables pointing to bar, as those variables are already present.
  • The second invocation of Cargo then invokes rustc by using the RUSTCenvironment variable and skipping the proxy, which results in the footoolchain being invoked. Previous versions of rustup invoked the proxy instead, which would correctly detect and use the bar toolchain.

Rustup 1.25.1 fixes this regression by reverting the change. The rustup working group is discussing in issue #3035 plans to re-introduce the change in a future release while avoiding breakage.

Thanks

Thanks again to all the contributors who made rustup 1.25.1 possible!

  • Daniel Silverstone (kinnison)
  • Robert Collins (rbtcollins)
  • Joshua Nelson (jyn514)
  • Pietro Albini (pietroalbini)

Continue Reading…

Rust Blog

Announcing Rustup 1.25.0

The rustup working group is happy to announce the release of rustup version 1.25.0. Rustup is the recommended tool to install Rust, a programming language that is empowering everyone to build reliable and efficient software.

If you have a previous version of rustup installed, getting rustup 1.25.0 is as easy as stopping any programs which may be using Rustup (e.g. closing your IDE) and running:

rustup self update

Rustup will also automatically update itself at the end of a normal toolchain update:

rustup update

If you don't have it already, you can get rustup from the appropriate page on our website.

What's new in rustup 1.25.0

This version of Rustup involves a significant number of internal cleanups, both in terms of the Rustup code and its documentation. In addition to a lot of work on the codebase itself, due to the length of time since the last release this one has a record number of contributors and we thank you all for your efforts and time.

One of the biggest changes in 1.25.0 is the new offer on Windows installs to auto-install the Visual Studio 2022 compilers which should simplify the process of getting started for people not used to developing on Windows with the MSVC-compatible toolchains.

A second important change for 1.25.0 is a number of PRs focussed around startup performance for Rustup. While it may not seem all that important to many, Rustup's startup time is a factor in the time it takes to do builds which involve large numbers of crates on systems which do not have large numbers of CPU cores. Hopefully the people for whom this is a common activity will notice an improvement; though there's more opportunity to speed things up still available.

Some, but by no means all, of the rest of this release's highlights includes support forrustup default none to unset the default toolchain, support for Windows arm64, inclusion of rust-gdbgui as a proxy so that platforms which support it can use GDB's gui mode with Rust, and some improvements to rustup-init.sh.

Full details are available in the changelog!

Rustup's documentation is also available in the rustup book.

Thanks

Thanks again to all the contributors who made rustup 1.25.0 possible!

  • 二手掉包工程师 (hi-rustin)
  • Brian Bowman (Seeker14491)
  • Jon Gjengset (jonho)
  • pierwill
  • Daniel Silverstone (kinnison)
  • Robert Collins (rbtcollins)
  • Alan Somers (asomers)
  • Brennan Vincent (umanwizard)
  • Joshua Nelson (jyn514)
  • Eric Huss (ehuss)
  • Will Bush (willbush)
  • Thad Guidry (thadguidry)
  • Alexander Lovchin (alovchin91)
  • zoodirector
  • Takayuki Nakata (giraffate)
  • Yusuke Abe (chansuke)
  • Wyatt Carss (wcarss)
  • Sondre Aasemoen (sondr3)
  • facklambda
  • Chad Dougherty (crd477)
  • Noritada Kobayashi (noritada)
  • Milan (mdaverde)
  • Pat Sier (pjsier)
  • Matt Keeter (mkeeter)
  • Alex Macleod (alexendoo)
  • Sathwik Matsa (sathwikmatsa)
  • Kushal Das (kushaldas)
  • Justus Winter (teythoon)
  • k900
  • Nicolas Ambram (nico-abram)
  • Connor Slade (basicprogrammer10)
  • Yerkebulan Tulibergenov (yerke)
  • Caleb Cartwright (calebcartwright)
  • Matthias Beyer (matthiasbeyer)
  • spacemaniac
  • Alex Touchet (atouchet)
  • Guillaume Gomez (guillaumegomez)
  • Chris Denton (chrisdenton)
  • Thomas Orozco (krallin)
  • cui fliter (cuishuang)
  • Martin Nordholts (enselic)
  • Emil Gardström (emilgardis)
  • Arlo Siemsen (arlosi)

Continue Reading…

Rust Blog

RLS Deprecation

The Rust Language Server (RLS) is being deprecated in favor of rust-analyzer. Current users of RLS should migrate to using rust-analyzer instead. Builds of RLS will continue to be released until at least the Rust 1.64 release (2022-09-22), after which no new releases will be made. This timeline may change if any issues arise.

RLS is an implementation of the Language Server Protocol (LSP) which provides enhanced features with any editor that supports the protocol, such as code-checking and refactoring. RLS was introduced by RFC 1317 and development was very active from 2016 through 2019. However, the architecture of RLS has several limitations that can make it difficult to provide low-latency and high-quality responses needed for an interactive environment.

Development of rust-analyzer began near the beginning of 2018 to provide an alternate LSP implementation for Rust. rust-analyzer uses a fundamentally different approach that does not rely on using rustc. In RFC 2912 rust-analyzer was adopted as the official replacement for RLS.

How you migrate to rust-analyzer will depend on which editor you are using. If you are using VSCode, you should uninstall the rust-lang.rust extension and install the official rust-lang.rust-analyzer extension. For other editors, please consult the rust-analyzer manual for instructions on how to install it.

Should you have any issues migrating to rust-analyzer, the Editors and IDEs category on the Rust Users forum is available for help with installation and usage.

We will soon be marking the official rust-lang.rust VSCode extension as deprecated, and will be implementing notifications that will inform users about the transition. After the end of release builds of RLS, we plan to replace the rls executable in official Rust releases with a small LSP implementation that informs the user that RLS is no longer available.

We would like to thank everyone who has worked on RLS and rust-analyzer. These options would not exist without the tremendous effort of all the contributors to these projects.

Continue Reading…

Rust Blog

Announcing Rust 1.62.0

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

If you have a previous version of Rust installed via rustup, you can get 1.62.0 with:

rustup update stable

If you don't have it already, you can get rustupfrom the appropriate page on our website, and check out thedetailed release notes for 1.62.0 on GitHub.

If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (rustup default beta) or the nightly channel (rustup default nightly). Please report any bugs you might come across!

What's in 1.62.0 stable

cargo add

You can now add new dependencies directly from the command line using cargo add. This command supports specifying features and versions. It can also be used to modify existing dependencies.

For example:

cargo add log
cargo add serde --features derive
cargo add nom@5

See the cargo documentation for more.

#[default] enum variants

You can now use #[derive(Default)] on enums if you specify a default variant. For example, until now you would have to manually write a Default impl for this enum:

#[derive(Default)]
enum Maybe<T> {
    #[default]
    Nothing,

    Something(T),
}

As of now only "unit" variants (variants that have no fields) are allowed to be marked #[default]. More information is available in the RFC for this feature.

Thinner, faster mutexes on Linux

Previously, Mutex, Condvar, and RwLock were backed by the pthreads library on Linux. The pthreads locks support more features than the Rust APIs themselves do, including runtime configuration, and are designed to be used in languages with fewer static guarantees than Rust provides.

The mutex implementation, for example, is 40 bytes and cannot be moved. This forced the standard library to allocate a Box behind the scenes for each new mutex for platforms that use pthreads.

Rust's standard library now ships with a raw futex-based implementation of these locks on Linux, which is very lightweight and doesn't require extra allocation. In 1.62.0 Mutex only needs 5 bytes for its internal state on Linux, though this may change in future versions.

This is part of a long effort to improve the efficiency of Rust's lock types, which includes previous improvements on Windows such as unboxing its primitives. You can read more about that effort in the tracking issue.

Bare metal x86_64 target

It's now easier to build OS-less binaries for x86_64, for example when writing a kernel. The x86_64-unknown-none target has been promoted to Tier 2 and can be installed with rustup.

rustup target add x86_64-unknown-none
rustc --target x86_64-unknown-none my_no_std_program.rs

You can read more about development using no_std in the Embedded Rust book.

Stabilized APIs

The following methods and trait implementations are now stabilized:

Other changes

There are other changes in the Rust 1.62.0 release. Check out what changed inRust,Cargo, and Clippy.

Contributors to 1.62.0

Many people came together to create Rust 1.62.0. We couldn't have done it without all of you.Thanks!

Continue Reading…

Rust Blog

Announcing The RustConf PostConf UnConf

Hello Rust community!

We're excited to announce that the Rust project teams will be hosting an unconference1 the day after RustConf.

RustConf PostConf UnConf promo image

The PostConf Unconf will be dedicated to the Rust project and will be a fantastic opportunity for users, contributors, and maintainers to network and discuss the project's development.

There will be no set agenda; instead, attendees will decide what will be discussed together and can move freely between sessions to find ones in which they can contribute most effectively based on their individual interests and needs.

To get the most out of the unconference, jot down your thoughts ahead of time and bring them ready to share. We will also set up a channel in the RustConf Discord for folks to communicate and make preliminary, informal plans.

If you plan to attend, please register as soon as possible to help us plan appropriately. If space is limited, project participants and conference attendees will be given preference. Registration is free and open to everyone, but we require either a RustConf registration ID or a $10 deposit at signup to ensure that registrations are an accurate approximation of participants.

🚨Register Now!🚨

We hope to see you there!

  1. If you are unfamiliar with the notion of an unconference, you may find this informational piece helpful.

Continue Reading…

Rust Blog

Call for testing: Cargo sparse-registry

The Cargo nightly sparse-registry feature is ready for testing. The feature causes Cargo to access the crates.io index over HTTP, rather than git. It can provide a significant performance improvement, especially if the local copy of the git index is out-of-date or not yet cloned.

Overview

To try it out, add the -Z sparse-registry flag on a recent nightly build of Cargo. For example, to update dependencies:

rustup update nightly
cargo +nightly -Z sparse-registry update

The feature can also be enabled by setting the environment variableCARGO_UNSTABLE_SPARSE_REGISTRY=true. Setting this variable will have no effect on stable Cargo, making it easy to opt-in for CI jobs.

The minimum Cargo version is cargo 2022-06-17, which is bundled with rustc 2022-06-20.

You can leave feedback on the internals thread.

If you see any issues please report them on the Cargo repo. The output of Cargo with the environment variable CARGO_LOG=cargo::sources::registry::http_remote=trace set will be helpful in debugging.

Details

Accessing the index over HTTP allows crates.io to continue growing without hampering performance. The current git index continues to grow as new crates are published, and clients must download the entire index. The HTTP index only requires downloading metadata for crates in your dependency tree.

The performance improvement for clients should be especially noticeable in CI environments, particularly if no local cache of the index exists.

On the server side, the HTTP protocol is much simpler to cache on a CDN, which improves scalability and reduces server load. Due to this caching, crate updates may take an extra minute to appear in the index.

The Cargo team plans to eventually make this the default way to access crates.io (though the git index will remain for compatibility with older versions of Cargo and external tools). Cargo.lock files will continue to reference the existing crates.io index on GitHub to avoid churn.

The -Z sparse-registry flag also enables alternative registries to be accessed over HTTP. For more details, see the tracking issue.

Thank you

This project has been in the works for over 2.5 years with collaboration from the crates.io, infra, and Cargo teams.

@kornelski wrote the sparse-index RFC and initial performance proof of concept. @jonhoo created the initial implementation in Cargo and gathered performance data. @arlosicompleted the implementation in Cargo and implemented the changes to crates.io to serve the index. @eh2406 provided numerous reviews and feedback to get all the changes landed. Many others from the community helped by providing suggestions, feedback, and testing.

Thank you to everyone involved!

Continue Reading…

Rust Blog

Announcing Rust 1.61.0

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

If you have a previous version of Rust installed via rustup, you can get 1.61.0 with:

rustup update stable

If you don't have it already, you can get rustupfrom the appropriate page on our website, and check out thedetailed release notes for 1.61.0 on GitHub.

If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (rustup default beta) or the nightly channel (rustup default nightly). Please report any bugs you might come across!

What's in 1.61.0 stable

Custom exit codes from main

In the beginning, Rust main functions could only return the unit type () (either implicitly or explicitly), always indicating success in the exit status, and if you wanted otherwise you had to call process::exit(code). Since Rust 1.26, main has been allowed to return a Result, where Ok translated to a C EXIT_SUCCESS andErr to EXIT_FAILURE (also debug-printing the error). Under the hood, these alternate return types were unified by an unstable Termination trait.

In this release, that Termination trait is finally stable, along with a more general ExitCodetype that wraps platform-specific return types. That has SUCCESS and FAILURE constants, and also implements From<u8> for more arbitrary values. The Termination trait can also be implemented for your own types, allowing you to customize any kind of reporting before converting to an ExitCode.

For example, here's a type-safe way to write exit codes for a git bisect run script:

use std::process::{ExitCode, Termination};

#[repr(u8)]
pub enum GitBisectResult {
    Good = 0,
    Bad = 1,
    Skip = 125,
    Abort = 255,
}

impl Termination for GitBisectResult {
    fn report(self) -> ExitCode {
        // Maybe print a message here
        ExitCode::from(self as u8)
    }
}

fn main() -> GitBisectResult {
    std::panic::catch_unwind(|| {
        todo!("test the commit")
    }).unwrap_or(GitBisectResult::Abort)
}

More capabilities for const fn

Several incremental features have been stabilized in this release to enable more functionality inconst functions:

  • Basic handling of fn pointers: You can now create, pass, and cast function pointers in aconst fn. For example, this could be useful to build compile-time function tables for an interpreter. However, it is still not permitted to call fn pointers.
  • Trait bounds: You can now write trait bounds on generic parameters to const fn, such asT: Copy, where previously only Sized was allowed.
  • dyn Trait types: Similarly, const fn can now deal with trait objects, dyn Trait.
  • impl Trait types: Arguments and return values for const fn can now be opaque impl Traittypes.

Note that the trait features do not yet support calling methods from those traits in a const fn.

See the Constant Evaluation section of the reference book to learn more about the current capabilities of const contexts, and future capabilities can be tracked in rust#57563.

Static handles for locked stdio

The three standard I/O streams -- Stdin, Stdout, and Stderr -- each have a lock(&self) to allow more control over synchronizing read and writes. However, they returned lock guards with a lifetime borrowed from &self, so they were limited to the scope of the original handle. This was determined to be an unnecessary limitation, since the underlying locks were actually in static storage, so now the guards are returned with a 'static lifetime, disconnected from the handle.

For example, a common error came from trying to get a handle and lock it in one statement:

// error[E0716]: temporary value dropped while borrowed
let out = std::io::stdout().lock();
//        ^^^^^^^^^^^^^^^^^       - temporary value is freed at the end of this statement
//        |
//        creates a temporary which is freed while still in use

Now the lock guard is 'static, not borrowing from that temporary, so this works!

Stabilized APIs

The following methods and trait implementations are now stabilized:

The following previously stable functions are now const:

Other changes

There are other changes in the Rust 1.61.0 release. Check out what changed inRust,Cargo, and Clippy.

In a future release we're planning to increase the baseline requirements for the Linux kernel to version 3.2, and for glibc to version 2.17. We'd love your feedback in rust#95026.

Contributors to 1.61.0

Many people came together to create Rust 1.61.0. We couldn't have done it without all of you.Thanks!

Continue Reading…

Rust Blog

Security advisory: malicious crate rustdecimal

This is a cross-post of the official security advisory. The official advisory contains a signed version with our PGP key, as well.

The Rust Security Response WG and the crates.io team were notified on 2022-05-02 of the existence of the malicious crate rustdecimal, which contained malware. The crate name was intentionally similar to the name of the popular rust_decimal crate, hoping that potential victims would misspell its name (an attack called "typosquatting").

To protect the security of the ecosystem, the crates.io team permanently removed the crate from the registry as soon as it was made aware of the malware. An analysis of all the crates on crates.io was also performed, and no other crate with similar code patterns was found.

Keep in mind that the rust_decimal crate was not compromised, and it is still safe to use.

Analysis of the crate

The crate had less than 500 downloads since its first release on 2022-03-25, and no crates on the crates.io registry depended on it.

The crate contained identical source code and functionality as the legitrust_decimal crate, except for the Decimal::new function.

When the function was called, it checked whether the GITLAB_CI environment variable was set, and if so it downloaded a binary payload into/tmp/git-updater.bin and executed it. The binary payload supported both Linux and macOS, but not Windows.

An analysis of the binary payload was not possible, as the download URL didn't work anymore when the analysis was performed.

Recommendations

If your project or organization is running GitLab CI, we strongly recommend checking whether your project or one of its dependencies depended on therustdecimal crate, starting from 2022-03-25. If you notice a dependency on that crate, you should consider your CI environment to be compromised.

In general, we recommend regularly auditing your dependencies, and only depending on crates whose author you trust. If you notice any suspicious behavior in a crate's source code please follow the Rust security policy and report it to the Rust Security Response WG.

Acknowledgements

We want to thank GitHub user @safinaskar for identifying the malicious crate in this GitHub issue.

Continue Reading…

Rust Blog

Announcing Rust 1.60.0

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

If you have a previous version of Rust installed via rustup, you can get 1.60.0 with:

rustup update stable

If you don't have it already, you can get rustupfrom the appropriate page on our website, and check out thedetailed release notes for 1.60.0 on GitHub. If you'd like to help us out by testing future releases, you might consider updating locally to use the beta channel (rustup default beta) or the nightly channel (rustup default nightly). Please report any bugs you might come across!

What's in 1.60.0 stable

Source-based Code Coverage

Support for LLVM-based coverage instrumentation has been stabilized in rustc. You can try this out on your code by rebuilding your code with -Cinstrument-coverage, for example like this:

RUSTFLAGS=&quot;-C instrument-coverage&quot; cargo build

After that, you can run the resulting binary, which will produce adefault.profraw file in the current directory. (The path and filename can be overriden by an environment variable; seedocumentationfor details).

The llvm-tools-preview component includes llvm-profdata for processing and merging raw profile output (coverage region execution counts); and llvm-covfor report generation. llvm-cov combines the processed output, fromllvm-profdata, and the binary itself, because the binary embeds a mapping from counters to actual source code regions.

rustup component add llvm-tools-preview
$(rustc --print sysroot)/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-profdata merge -sparse default.profraw -o default.profdata
$(rustc --print sysroot)/lib/rustlib/x86_64-unknown-linux-gnu/bin/llvm-cov show -Xdemangler=rustfilt target/debug/coverage-testing \
    -instr-profile=default.profdata \
    -show-line-counts-or-regions \
    -show-instantiations

The above commands on a simple helloworld binary produce this annotated report, showing that each line of the input was covered.

 1|      1|fn main() {
    2|      1|    println!(&quot;Hello, world!&quot;);
    3|      1|}

For more details, please read thedocumentation in the rustc book. The baseline functionality is stable and will exist in some form in all future Rust releases, but the specific output format and LLVM tooling which produces it are subject to change. For this reason, it is important to make sure that you use the same version for both the llvm-tools-preview and the rustc binary used to compile your code.

cargo --timings

Cargo has stabilized support for collecting information on build with the --timings flag.

$ cargo build --timings
   Compiling hello-world v0.1.0 (hello-world)
      Timing report saved to target/cargo-timings/cargo-timing-20220318T174818Z.html
    Finished dev [unoptimized + debuginfo] target(s) in 0.98s

The report is also copied to target/cargo-timings/cargo-timing.html. A report on the release build of Cargo has been put up here. These reports can be useful for improving build performance. More information about the timing reports may be found in the documentation.

New syntax for Cargo features

This release introduces two new changes to improve support for Cargo features and how they interact with optional dependencies: Namespaced dependencies and weak dependency features.

Cargo has long supported features along with optional dependencies, as illustrated by the snippet below.

[dependencies]
jpeg-decoder = { version = &quot;0.1.20&quot;, default-features = false, optional = true }

[features]
# Enables parallel processing support by enabling the &quot;rayon&quot; feature of jpeg-decoder.
parallel = [&quot;jpeg-decoder/rayon&quot;]

There are two things to note in this example:

  • The optional dependency jpeg-decoder implicitly defines a feature of the same name. Enabling the jpeg-decoder feature will enable the jpeg-decoder dependency.
  • The &quot;jpeg-decoder/rayon&quot; syntax enables the jpeg-decoder dependency and enables the jpeg-decoder dependency's rayon feature.

Namespaced features tackles the first issue. You can now use the dep: prefix in the [features] table to explicitly refer to an optional dependency without implicitly exposing it as a feature. This gives you more control on how to define the feature corresponding to the optional dependency including hiding optional dependencies behind more descriptive feature names.

Weak dependency features tackle the second issue where the &quot;optional-dependency/feature-name&quot; syntax would always enable optional-dependency. However, often you want to enable the feature on the optional dependency only if some other feature has enabled the optional dependency. Starting in 1.60, you can add a ? as in &quot;package-name?/feature-name&quot; which will only enable the given feature if something else has enabled the optional dependency.

For example, let's say we have added some serialization support to our library, and it requires enabling a corresponding feature in some optional dependencies. That can be done like this:

[dependencies]
serde = { version = &quot;1.0.133&quot;, optional = true }
rgb = { version = &quot;0.8.25&quot;, optional = true }

[features]
serde = [&quot;dep:serde&quot;, &quot;rgb?/serde&quot;]

In this example, enabling the serde feature will enable the serde dependency. It will also enable the serde feature for the rgb dependency, but only if something else has enabled the rgb dependency.

Incremental compilation status

Incremental compilation is re-enabled for the 1.60 release. The Rust team continues to work on fixing bugs in incremental, but no problems causing widespread breakage are known at this time, so we have chosen to reenable incremental compilation. Additionally, the compiler team is continuing to work on long-term strategy to avoid future problems of this kind. That process is in relatively early days, so we don't have anything to share yet on that front.

Instant monotonicity guarantees

On all platforms Instant will try to use an OS API that guarantees monotonic behavior if available (which is the case on all tier 1 platforms). In practice such guarantees are -- under rare circumstances -- broken by hardware, virtualization, or operating system bugs. To work around these bugs and platforms not offering monotonic clocks, Instant::duration_since, Instant::elapsed andInstant::sub now saturate to zero. In older Rust versions this led to a panic instead. Instant::checked_duration_since can be used to detect and handle situations where monotonicity is violated, or Instants are subtracted in the wrong order.

This workaround obscures programming errors where earlier and later instants are accidentally swapped. For this reason future Rust versions may reintroduce panics in at least those cases, if possible and efficient.

Prior to 1.60, the monotonicity guarantees were provided through mutexes or atomics in std, which can introduce large performance overheads toInstant::now(). Additionally, the panicking behavior meant that Rust software could panic in a subset of environments, which was largely undesirable, as the authors of that software may not be able to fix or upgrade the operating system, hardware, or virtualization system they are running on. Further, introducing unexpected panics into these environments made Rust software less reliable and portable, which is of higher concern than exposing typically uninteresting platform bugs in monotonic clock handling to end users.

Stabilized APIs

The following methods and trait implementations are now stabilized:

Other changes

There are other changes in the Rust 1.60.0 release. Check out what changed inRust,Cargo, and Clippy.

Contributors to 1.60.0

Many people came together to create Rust 1.60.0. We couldn't have done it without all of you.Thanks!

Continue Reading…

Rust Blog

Security advisory for the regex crate (CVE-2022-24713)

This is a cross-post of the official security advisory. The official advisory contains a signed version with our PGP key, as well.

The Rust Security Response WG was notified that the regex crate did not properly limit the complexity of the regular expressions (regex) it parses. An attacker could use this security issue to perform a denial of service, by sending a specially crafted regex to a service accepting untrusted regexes. No known vulnerability is present when parsing untrusted input with trusted regexes.

This issue has been assigned CVE-2022-24713. The severity of this vulnerability is "high" when the regex crate is used to parse untrusted regexes. Other uses of the regex crate are not affected by this vulnerability.

Overview

The regex crate features built-in mitigations to prevent denial of service attacks caused by untrusted regexes, or untrusted input matched by trusted regexes. Those (tunable) mitigations already provide sane defaults to prevent attacks. This guarantee is documented and it's considered part of the crate's API.

Unfortunately a bug was discovered in the mitigations designed to prevent untrusted regexes to take an arbitrary amount of time during parsing, and it's possible to craft regexes that bypass such mitigations. This makes it possible to perform denial of service attacks by sending specially crafted regexes to services accepting user-controlled, untrusted regexes.

Affected versions

All versions of the regex crate before or equal to 1.5.4 are affected by this issue. The fix is include starting from regex 1.5.5.

Mitigations

We recommend everyone accepting user-controlled regexes to upgrade immediately to the latest version of the regex crate.

Unfortunately there is no fixed set of problematic regexes, as there are practically infinite regexes that could be crafted to exploit this vulnerability. Because of this, we do not recommend denying known problematic regexes.

Acknowledgements

We want to thank Addison Crump for responsibly disclosing this to us according to the Rust security policy, and for helping review the fix.

We also want to thank Andrew Gallant for developing the fix, and Pietro Albini for coordinating the disclosure and writing this advisory.

Continue Reading…

Rust Blog

Announcing Rust 1.59.0

The Rust team has published a new version of Rust, 1.59.0. Rust is a programming language that is empowering everyone to build reliable and efficient software.


Today's release falls on the day in which the world's attention is captured by the sudden invasion of Ukraine by Putin's forces. Before going into the details of the new Rust release, we'd like to state that we stand in solidarity with the people of Ukraine and express our support for all people affected by this conflict.


If you have a previous version of Rust installed via rustup, you can get 1.59.0 with:

rustup update stable

If you don't have it already, you can get rustupfrom the appropriate page on our website, and check out thedetailed release notes for 1.59.0 on GitHub.

What's in 1.59.0 stable

Inline assembly

The Rust language now supports inline assembly. This enables many applications that need very low-level control over their execution, or access to specialized machine instructions.

When compiling for x86-64 targets, for instance, you can now write:

use std::arch::asm;

// Multiply x by 6 using shifts and adds
let mut x: u64 = 4;
unsafe {
    asm!(
        &quot;mov {tmp}, {x}&quot;,
        &quot;shl {tmp}, 1&quot;,
        &quot;shl {x}, 2&quot;,
        &quot;add {x}, {tmp}&quot;,
        x = inout(reg) x,
        tmp = out(reg) _,
    );
}
assert_eq!(x, 4 * 6);

The format string syntax used to name registers in the asm! and global_asm!macros is the same used in Rust format strings, so it should feel quite familiar to Rust programmers.

The assembly language and instructions available with inline assembly vary according to the target architecture. Today, the stable Rust compiler supports inline assembly on the following architectures:

  • x86 and x86-64
  • ARM
  • AArch64
  • RISC-V

You can see more examples of inline assembly in Rust By Example, and find more detailed documentation in the reference.

Destructuring assignments

You can now use tuple, slice, and struct patterns as the left-hand side of an assignment.

let (a, b, c, d, e);

(a, b) = (1, 2);
[c, .., d, _] = [1, 2, 3, 4, 5];
Struct { e, .. } = Struct { e: 5, f: 3 };

assert_eq!([1, 2, 1, 4, 5], [a, b, c, d, e]);

This makes assignment more consistent with let bindings, which have long supported the same thing. Note that destructuring assignments with operators such as += are not allowed.

Const generics defaults and interleaving

Generic types can now specify default values for their const generics. For example, you can now write the following:

struct ArrayStorage&lt;T, const N: usize = 2&gt; {
    arr: [T; N],
}

impl&lt;T&gt; ArrayStorage&lt;T&gt; {
    fn new(a: T, b: T) -&gt; ArrayStorage&lt;T&gt; {
        ArrayStorage {
            arr: [a, b],
        }
    }
}

Previously, type parameters were required to come before all const parameters. That restriction has been relaxed and you can now interleave them.

fn cartesian_product&lt;
    T, const N: usize,
    U, const M: usize,
    V, F
&gt;(a: [T; N], b: [U; M]) -&gt; [[V; N]; M]
where
    F: FnMut(&amp;T, &amp;U) -&gt; V
{
    // ...
}

Future incompatibility warnings

Sometimes bugs in the Rust compiler cause it to accept code that should not have been accepted. An example of this was borrows of packed structfields being allowed in safe code.

While this happens very rarely, it can be quite disruptive when a crate used by your project has code that will no longer be allowed. In fact, you might not notice until your project inexplicably stops building!

Cargo now shows you warnings when a dependency will be rejected by a future version of Rust. After running cargo build or cargo check, you might see:

warning: the following packages contain code that will be rejected by a future version of Rust: old_dep v0.1.0
note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`

You can run the cargo report command mentioned in the warning to see a full report of the code that will be rejected. This gives you time to upgrade your dependency before it breaks your build.

Creating stripped binaries

It's often useful to strip unnecessary information like debuginfo from binaries you distribute, making them smaller.

While it has always been possible to do this manually after the binary is created, cargo and rustc now support stripping when the binary is linked. To enable this, add the following to your Cargo.toml:

[profile.release]
strip = &quot;debuginfo&quot;

This causes debuginfo to be stripped from release binaries. You can also supply&quot;symbols&quot; or just true to strip all symbol information where supported.

The standard library typically ships with debug symbols and line-level debuginfo, so Rust binaries built without debug symbols enabled still include the debug information from the standard library by default. Using the stripoption allows you to remove this extra information, producing smaller Rust binaries.

See Cargo's documentation for more details.

Incremental compilation off by default

The 1.59.0 release disables incremental by default (unless explicitly asked for by via an environment variable: RUSTC_FORCE_INCREMENTAL=1). This mitigates the effects of a known bug, #94124, which can cause deserialization errors (and panics) during compilation with incremental compilation turned on.

The specific fix for #94124 has landed and is currently in the 1.60 beta, which will ship in six weeks. We are not presently aware of other issues that would encourage a decision to disable incremental in 1.60 stable, and if none arise it is likely that 1.60 stable will re-enable incremental compilation again. Incremental compilation remains on by default in the beta and nightly channels.

As always, we encourage users to test on the nightly and beta channels and report issues you find: particularly for incremental bugs, this is the best way to ensure the Rust team can judge whether there is breakage and the number of users it affects.

Stabilized APIs

The following methods and trait implementations are now stabilized:

The following previously stable functions are now const:

Other changes

There are other changes in the Rust 1.59.0 release. Check out what changed inRust,Cargo, and Clippy.

Contributors to 1.59.0

Many people came together to create Rust 1.59.0. We couldn't have done it without all of you.Thanks!

Continue Reading…

Rust Blog

rust-analyzer joins the Rust organization!

We have an exciting announcement to make! The rust-analyzer project, a new implementation of the Language Server Protocol (LSP) for Rust, is now officially a part of the wider Rust organization! 🎉

We want to start by thanking everyone who has gotten us this far, from contributors, to sponsors, to all the users of rust-analyzer in the Rust community. We could not have done this without you.

The immediate impact of this organizational change is limited -- nothing changes for rust-analyzer users or contributors. However, this change unblocks technical work to make rust-analyzer the officially recommended language server for Rust in the near future.

If you were hesitant to try rust-analyzer before, today is a good opportunity to do so. Not only is it a very capable language server for Rust, but according to VS Code statistics, it is one of the best rated LSP implementations across programming languages. We highly recommend giving rust-analyzer a spin today, even if it will take some more time for us to complete the due process and switch from the existing officially recommended LSP implementation (RLS) properly.

rust-analyzer enjoys excellent support in many editors:

For other editors, check the manual.

Finally, if you are using IntelliJ-Platform based IDEs like CLion, IDEA or PyCharm, you don't need rust-analyzer. You should use the awesome IntelliJ Rust plugin by JetBrains.

History and Future

The rust-analyzer project was started at the very end of 2017 (first commit). At that time, the existing LSP implementation, RLS, had been providing IDE support for Rust for several years. While it handled well the most important features, it was clearly far from the experience offered by state-of-the-art IDEs for some other languages.

Originally, the plan was to just experiment with error-resilient parsing for Rust; but when you have a good parser, it is so tempting to add a simple LSP server on top of it. Long story short, it took surprisingly little effort to get to a prototype which was already useful as an IDE, which happened in Autumn 2018. At that critical point, the company Ferrous Systems (which was newborn itself) stepped in to fund further development of the prototype.

During 2019, the then nascent rust-analyzer community worked hard to build out the foundation of an IDE. By 2020, we realized that what we had built was no longer a prototype, but an already tremendously useful tool for day-to-day Rust programming. This culminated in RFC2912: "Transition to rust-analyzer as our official LSP (Language Server Protocol) implementation". The RFC was accepted with overwhelming support from the community: it is still the most upvoted Rust RFC ever. However, there was a wrinkle in the plan -- rust-analyzer was not an official Rust project! That's what we are fixing today!

Next, we will proceed with the plan outlined in the RFC: advertising rust-analyzer as the very likely future of Rust IDE support, gathering feedback, and, conditioned on the positive outcome of that, sunsetting RLS, the currently recommended language server. So, once again -- do try out rust-analyzer and leave feedback on the tracking issues.

After the transition, we will double down on the technical side of things.

As exciting as rust-analyzer is today, it only scratches the surface of what's possible when you bring the compiler's intricate understanding of the code right into the text editor. The end-game we are aiming for is creating an API to analyze and transform Rust code with full access to semantics.

Funding

One of the hardest nuts to crack for the present transition was the question of funding. Today, Rust is organized as a set of somewhat independent projects (rustc, cargo, rustup, rustfmt), and there's deliberately no way to fund a specific project directly. The new Rust Foundation is the official place to sponsor Rust in general, with the Foundation Board overseeing funds allocation. Yet, it has always been encouraged for individuals to seek individual funding. While the Rust project may advertise funding opportunities for individual contributors, it does not officially endorse these efforts nor does it facilitate the funding of entire teams.

rust-analyzer has received a significant share of funds from its OpenCollective and later GitHub Sponsors, managed by Ferrous Systems. This OpenCollective funded efforts by both individual contributors and Ferrous Systems employees. Details of this can be found in their transparency reports.

Luckily, the OpenCollective has always been managed in a way that would make it possible to transfer it to a different account holder. With this transition, the OpenCollective will be renamed from "rust-analyzer OpenCollective" to "Ferrous Systems OpenCollective (rust-analyzer)". This allows current sponsors to continue to sponsor and also make it clear that their chosen project will continue to be funded.

In a sense, the OpenCollective is handed to Ferrous Systems. All Sponsor credits will move to https://ferrous-systems.com/open-source/#sponsors.

We would like to thank Ferrous Systems for their openness and flexibility in the process, for their thoughtfulness in making sure the funding situation around rust-analyzer was clear, and for taking on the effort of fundraising.

Eventually the rust-analyzer GitHub Sponsors will also move away from the rust-analyzer GitHub organisation.

And of course, another great way for companies to support rust-analyzer development is to hire the people working on rust-analyzer to continue to do so.

Thanks

We'd like to once again thank everyone who help get rust-analyzer to this point. From experiment to being well on its way to the officially recommended LSP implementation for Rust, we couldn't have done it without the help of our contributors, sponsors, and users.

Conclusion

So that's where we are at right now! Thanks to the awesome contributors to rustc, clippy, cargo, LSP, IntelliJ Rust, RLS and rust-analyzer, Rust today already enjoys great IDE support, even if it still has a bit of experimental flair to it.

Continue Reading…

Rust Blog

Rust Survey 2021 Results

Blog Post

Greetings Rustaceans!

Another year has passed, and with it comes another annual Rust survey analysis! The survey was conducted in December 2021.

We’d like to thank everyone who participated in this year’s survey, with a special shout-out to those who helped translate the survey from English into other languages.

Without further ado, let’s dive into the analysis!

A Global Community

The Rust community continues to grow, with this survey having the largest number of complete survey responses (9354 respondents), exceeding last year's total by roughly 1500 responses.

90% of respondents said that they use Rust for any purpose, while 5% stated they had used Rust at some point in the past but no longer do, and 4% stated they have yet to use Rust at all.

The survey was offered in 10 languages with 78% filling out the survey in English followed by Simplified Chinese (6%), German (4%), and French (3%). Despite English being the language most respondents completed the survey in, respondents hailed from all around the world. The United States was the country with the largest representation at 24% followed by Germany (12%), China (7%), and the U.K. (6%). In total 113 different countries and territories were represented through this survey!

English, however, is not the language of choice for all Rustaceans with nearly 7% preferring not to use English as a language for technical communication. An additional 23% of respondents prefer another language in addition to English. The most commonly preferred languages (besides English) roughly follow where Rustaceans live with Simplified Chinese, German, and French being the top 3. However, Japanese, Simplified Chinese, and Russian speakers were the most likely to prefer not to use English at all for technical conversation.

Using Rust

The percentage of people using Rust continues to rise. Of those using Rust, 81% are currently using it on at least a weekly basis compared to 72% from last year's survey.

75% of all Rust users say they can write production ready code, though 27% say that it is at times a struggle.

Rust expertise

Overall, Rustaceans seem to be having a great time writing Rust with only 1% saying it isn't fun to use. Only a quarter of a percent find Rust doesn't have any real benefit over other programming languages.

Rust at Work

Rust can now safely be classified as a language used by people in professional settings. Of those respondents using Rust, 59% use it at least occasionally at work with 23% using Rust for the majority of their coding. This is a large increase over last year where only 42% of respondents used Rust at work.

Do you use Rust at work?

Adopting Rust at work seems to follow a long but ultimately worthwhile path for a lot of Rustaceans. First, 83% of those who have adopted Rust at work found it to be "challenging". How much this is related to Rust itself versus general challenges with adopting a new programming language, however, is unclear. During adoption only 13% of respondents found the language was slowing their team down and 82% found that Rust helped their teams achieve their goals.

After adoption, the costs seem to be justified: only 1% of respondents did not find the challenge worth it while 79% said it definitely was. When asked if their teams were likely to use Rust again in the future, 90% agreed. Finally, of respondents using Rust at work, 89% of respondents said their teams found it fun and enjoyable to program.

As for why respondents are using Rust at work, the top answer was that it allowed users "to build relatively correct and bug free software" with 96% of respondents agreeing with that statement. After correctness, performance (92%) was the next most popular choice. 89% of respondents agreed that they picked Rust at work because of Rust's much-discussed security properties.

Adopting Rust

Overall, Rust seems to be a language ready for the challenges of production, with only 3% of respondents saying that Rust was a "risky" choice for production use.

Challenges Ahead

Overall, the annual survey points towards a growing, healthy community of Rustaceans, but this is not to say we don't have work ahead of us. Compile times, a historical focus of improvement for the Rust project, continue to not be where they need to be, with 61% of respondents saying work still needs to be done to improve them. Although, to the compiler team's credit, 61% found that they improved over the past year. Other areas indicated as in need of more improvement were disk space (45%), debugging (40%), and GUI development (56%).

The IDE experience (led through continued adoption and improvement of various tools like rust-analyzer, IntelliJ Rust, etc.) gets the prize for showing the most improvement: 56% found it has improved over the last year.

However, compiler error messages received the most praise, with 90% approval of their current state. 🎉

When asked what their biggest worries for the future of Rust are, the top answer was a fear that there will not be enough usage in industry (38%). Given that Rust continues to show strides in adoption at places of work, the community seems to be on a good path to overcoming this concern.

The next largest concern was that the language would become too complex (33%). This was combined with a relative small number of folks calling for additional features (especially for ones not already in the pipeline).

Finally, the third largest concern was that those working on Rust would not find the proper support they need to continue to develop the language and community in a healthy way (30%). With the establishment of the Rust Foundation, support structures are coming into place that hopefully will address this point, but no doubt plenty of work is still ahead of us.

An Exciting Future

2021 was arguably one of the most significant years in Rust's history - with the establishment of the Rust foundation, the 2021 edition, and a larger community than ever, Rust seems to be on a solid path as we head into the future.

Plenty of work remains, but here's hoping for a great 2022!

Continue Reading…

Rust Blog

Crates.io Index Snapshot Branches Moving

Every so often, the crates.io index's Git history is squashed into onecommitto minimize the history Cargo needs to download. When the index is squashed, we save snapshots to preserve the history of crate publishes.

Currently, those snapshots are stored as branches in the main index Git repository. Those branches are using server resources though, as the server still has to consider their contents whenever Cargo asks for the master branch. We will be deleting the snapshot branches from this repository to ensure that all objects referenced in the master branch will only be compressed against other objects in the master branch, ensuring that the current clone behavior will be much more efficient on the server side.

Here's how this might affect you:

If you use Cargo

You should not see any effects from this change. Cargo does not use the snapshot branches, and Cargo regularly handles index squashes. If you do see any issues, they are a bug, please reportthem on the Cargo repo.

If you use the snapshot branches

In one week, on 2022-02-21, we will be removing all snapshot branches from the crates.io-index repo. All snapshot branches, both historical and in the future, are and will be in therust-lang/crates.io-index-archive repoinstead. Please update any scripts or tools referencing the snapshot branches by that time.

In the future

In the medium term, we're working to prioritize the completion of in-progresswork to add a way to serve the index as static files on HTTP, which will further ease the server load. The index repository will not be going away so that older versions of Cargo will continue to work. See RFC2789 for more details.

Continue Reading…

Rust Blog

Changes in the Core Team

We want to say thanks to three people who recently have decided to step back from the Core Team:

  • Steve Klabnik is leaving the Core Team and the Security Response Working Group.
    Steve started with Rust more than 9 years ago.
    He was the primary author of the Rust Programming Language book and part of the core team since 2014. He has been running the @rustlang Twitter account and as such formed a lot of the “voice” of the project.
    Steve will now be able to focus on using Rust instead of making Rust.
  • Florian Gilcher is stepping back from all of his project positions.
    He became a Core Team observer in 2019 and a full Core Team member in 2020.
    He also served as a project director on the Rust foundation board.
    Before all of that he was part of the Community Team since 2015.
    As he's focusing on his company and taking on other business obligations, he is making space for others in the project.
  • Pietro Albini is leaving the Core Team to focus on other parts of the project, including the Infrastructure Team and the Security Response Working Group. He joined the Core Team in late 2019, shortly after becoming a co-lead of the Infrastructure Team, but the amount of work in the Core Team made it hard for him to spend enough time on his other roles in the project.

We're thankful for Steve's, Florian's and Pietro's contributions to the Core Team & the Rust project in the past and we’re looking forward to any contributions they will still make in the future.

Continue Reading…

Rust Blog

Announcing Rust 1.58.1

The Rust team has published a new point release of Rust, 1.58.1. 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.58.1 is as easy as:

rustup update stable

If you don't have it already, you can get rustup from the appropriate page on our website.

What's in 1.58.1 stable

Rust 1.58.1 fixes a race condition in the std::fs::remove_dir_all standard library function. This security vulnerability is tracked as CVE-2022-21658, and you can read more about it on the advisory we published earliertoday. We recommend all users to update their toolchain immediately and rebuild their programs with the updated compiler.

Rust 1.58.1 also addresses several regressions in diagnostics and tooling introduced in Rust 1.58.0:

  • The non_send_fields_in_send_ty Clippy lint was discovered to have too many
    false positives and has been moved to the experimental lints group (called
    "nursery").
  • The useless_format Clippy lint has been updated to handle captured
    identifiers in format strings, introduced in Rust 1.58.0.
  • A regression in Rustfmt preventing generated files from being formatted when
    passed through the standard input has been fixed.
  • An incorrect error message displayed by rustc in some cases has been fixed.

You can find more detailed information on the specific regressions in therelease notes.

Contributors to 1.58.1

Many people came together to create Rust 1.58.1. We couldn't have done it without all of you. Thanks!

Continue Reading…

Rust Blog

Security advisory for the standard library (CVE-2022-21658)

This is a cross-post of the official security advisory. The official advisory contains a signed version with our PGP key, as well.

The Rust Security Response WG was notified that the std::fs::remove_dir_allstandard library function is vulnerable a race condition enabling symlink following (CWE-363). An attacker could use this security issue to trick a privileged program into deleting files and directories the attacker couldn't otherwise access or delete.

This issue has been assigned CVE-2022-21658.

Overview

Let's suppose an attacker obtained unprivileged access to a system and needed to delete a system directory called sensitive/, but they didn't have the permissions to do so. If std::fs::remove_dir_all followed symbolic links, they could find a privileged program that removes a directory they have access to (called temp/), create a symlink from temp/foo to sensitive/, and wait for the privileged program to delete foo/. The privileged program would follow the symlink from temp/foo to sensitive/ while recursively deleting, resulting in sensitive/ being deleted.

To prevent such attacks, std::fs::remove_dir_all already includes protection to avoid recursively deleting symlinks, as described in its documentation:

This function does not follow symbolic links and it will simply remove the symbolic link itself.

Unfortunately that check was implemented incorrectly in the standard library, resulting in a TOCTOU (Time-of-check Time-of-use) race condition. Instead of telling the system not to follow symlinks, the standard library first checked whether the thing it was about to delete was a symlink, and otherwise it would proceed to recursively delete the directory.

This exposed a race condition: an attacker could create a directory and replace it with a symlink between the check and the actual deletion. While this attack likely won't work the first time it's attempted, in our experimentation we were able to reliably perform it within a couple of seconds.

Affected Versions

Rust 1.0.0 through Rust 1.58.0 is affected by this vulnerability. We're going to release Rust 1.58.1 later today, which will include mitigations for this vulnerability. Patches to the Rust standard library are also available for custom-built Rust toolchains here.

Note that the following targets don't have usable APIs to properly mitigate the attack, and are thus still vulnerable even with a patched toolchain:

  • macOS before version 10.10 (Yosemite)
  • REDOX

Mitigations

We recommend everyone to update to Rust 1.58.1 as soon as possible, especially people developing programs expected to run in privileged contexts (including system daemons and setuid binaries), as those have the highest risk of being affected by this.

Note that adding checks in your codebase before calling remove_dir_all willnot mitigate the vulnerability, as they would also be vulnerable to race conditions like remove_dir_all itself. The existing mitigation is working as intended outside of race conditions.

Acknowledgments

We want to thank Hans Kratz for independently discovering and disclosing this issue to us according to the Rust security policy, for developing the fix for UNIX-like targets and for reviewing fixes for other platforms.

We also want to thank Florian Weimer for reviewing the UNIX-like fix and for reporting the same issue back in 2018, even though the Security Response WG didn't realize the severity of the issue at the time.

Finally we want to thank Pietro Albini for coordinating the security response and writing this advisory, Chris Denton for writing the Windows fix, Alex Crichton for writing the WASI fix, and Mara Bos for reviewing the patches.

Continue Reading…

Rust Blog

Announcing Rust 1.58.0

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

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

rustup update stable

If you don't have it already, you can get rustupfrom the appropriate page on our website, and check out thedetailed release notes for 1.58.0 on GitHub.

What's in 1.58.0 stable

Rust 1.58 brings captured identifiers in format strings, a change to theCommand search path on Windows, more #[must_use] annotations in the standard library, and some new library stabilizations.

Captured identifiers in format strings

Format strings can now capture arguments simply by writing {ident} in the string. Formats have long accepted positional arguments (optionally by index) and named arguments, for example:

println!(&quot;Hello, {}!&quot;, get_person());                // implicit position
println!(&quot;Hello, {0}!&quot;, get_person());               // explicit index
println!(&quot;Hello, {person}!&quot;, person = get_person()); // named

Now named arguments can also be captured from the surrounding scope, like:

let person = get_person();
// ...
println!(&quot;Hello, {person}!&quot;); // captures the local `person`

This may also be used in formatting parameters:

let (width, precision) = get_format();
for (name, score) in get_scores() {
  println!(&quot;{name}: {score:width$.precision$}&quot;);
}

Format strings can only capture plain identifiers, not arbitrary paths or expressions. For more complicated arguments, either assign them to a local name first, or use the older name = expression style of formatting arguments.

This feature works in all macros accepting format strings. However, one corner case is the panic! macro in 2015 and 2018 editions, where panic!(&quot;{ident}&quot;)is still treated as an unformatted string -- the compiler will warn about this not having the intended effect. Due to the 2021 edition's update of panic macros for improved consistency, this works as expected in 2021 panic!.

Reduced Windows Command search path

On Windows targets, std::process::Command will no longer search the current directory for executables. That effect was owed to historical behavior of the win32 CreateProcess API, so Rust was effectively searching in this order:

  1. (Rust specific) The directories that are listed in the child's PATHenvironment variable, if it was explicitly changed from the parent.
  2. The directory from which the application loaded.
  3. The current directory for the parent process.
  4. The 32-bit Windows system directory.
  5. The 16-bit Windows system directory.
  6. The Windows directory.
  7. The directories that are listed in the PATH environment variable.

However, using the current directory can lead to surprising results, or even malicious behavior when dealing with untrusted directories. For example,ripgrep published CVE-2021-3013 when they learned that their child processes could be intercepted in this way. Even Microsoft's own PowerShelldocuments that they do not use the current directory for security.

Rust now performs its own search without the current directory, and the legacy 16-bit directory is also not included, as there is no API to discover its location. So the new Command search order for Rust on Windows is:

  1. The directories that are listed in the child's PATH environment variable.
  2. The directory from which the application loaded.
  3. The 32-bit Windows system directory.
  4. The Windows directory.
  5. The directories that are listed in the PATH environment variable.

Non-Windows targets continue to use their platform-specific behavior, most often only considering the child or parent PATH environment variable.

More #[must_use] in the standard library

The #[must_use] attribute can be applied to types or functions when failing to explicitly consider them or their output is almost certainly a bug. This has long been used in the standard library for types like Result, which should be checked for error conditions. This also helps catch mistakes such as expecting a function to mutate a value in-place, when it actually returns a new value.

Library proposal 35 was approved in October 2021 to audit and expand the application of #[must_use] throughout the standard library, covering many more functions where the primary effect is the return value. This is similar to the idea of function purity, but looser than a true language feature. Some of these additions were present in release 1.57.0, and now in 1.58.0 the effort has completed.

Stabilized APIs

The following methods and trait implementations were stabilized.

The following previously stable functions are now const.

Other changes

There are other changes in the Rust 1.58.0 release: check out what changed inRust,Cargo, and Clippy.

Contributors to 1.58.0

Many people came together to create Rust 1.58.0. We couldn't have done it without all of you.Thanks!

Continue Reading…

Rust Blog

Launching the 2021 State of Rust Survey

It's that time again! Time for us to take a look at who the Rust community is composed of, how the Rust project is doing, and how we can improve the Rust programming experience. The Rust Community Team is pleased to announce our 2021 State of Rust Survey! Whether or not you use Rust today, we want to know your opinions. Your responses will help the project understand its strengths and weaknesses, and establish development priorities for the future.

Completing this survey should take about 10–30 minutes and is anonymous. We will be accepting submissions for the next two weeks (until the 22nd of December), and we will write up our findings afterwards to blog.rust-lang.org. You can also check out last year’s results.

(If you speak multiple languages, please pick one)

Please help us spread the word by sharing the survey link on your social network feeds, at meetups, around your office, and in other communities.

If you have any questions, please see our frequently asked questions or email the Rust Community team at community-team@rust-lang.org.

Finally, we wanted to thank everyone who helped develop, polish, and test the survey. In particular, we'd like to thank all of the volunteers who worked to provide all of the translations available this year and who will help to translate the results.

Continue Reading…

Rust Blog

Announcing Rust 1.57.0

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

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

rustup update stable

If you don't have it already, you can get rustupfrom the appropriate page on our website, and check out thedetailed release notes for 1.57.0 on GitHub.

What's in 1.57.0 stable

Rust 1.57 brings panic! to const contexts, adds support for custom profiles to Cargo, and stabilizes fallible reservation APIs.

panic! in const contexts

With previous versions of Rust, the panic! macro was not usable in const fn and other compile-time contexts. Now, this has been stabilized. Together with the stabilization of panic!, several other standard library APIs are now usable in const, such as assert!.

This stabilization does not yet include the full formatting infrastructure, so the panic! macro must be called with either a static string (panic!(&quot;...&quot;)), or with a single &amp;str interpolated value (panic!(&quot;{}&quot;, a)) which must be used with {} (no format specifiers or other traits).

It is expected that in the future this support will expand, but this minimal stabilization already enables straightforward compile-time assertions, for example to verify the size of a type:

const _: () = assert!(std::mem::size_of::&lt;u64&gt;() == 8);
const _: () = assert!(std::mem::size_of::&lt;u8&gt;() == 1);

Cargo support for custom profiles

Cargo has long supported four profiles: dev, release, test, and bench. With Rust 1.57, support has been added for arbitrarily named profiles.

For example, if you want to enable link time optimizations (LTO) only when making the final production build, adding the following snippet to Cargo.toml enables the lto flag when this profile is selected, but avoids enabling it for regular release builds.

[profile.production]
inherits = &quot;release&quot;
lto = true

Note that custom profiles must specify a profile from which they inherit default settings. Once the profile has been defined, Cargo commands which build code can be asked to use it with --profile production. Currently, this will build artifacts in a separate directory (target/production in this case), which means that artifacts are not shared between directories.

Fallible allocation

Rust 1.57 stabilizes try_reserve for Vec, String, HashMap, HashSet, and VecDeque. This API enables callers to fallibly allocate the backing storage for these types.

Rust will usually abort the process if the global allocator fails, which is not always desirable. This API provides a method for avoiding that abort when working with the standard library collections. However, Rust does not guarantee that the returned memory is actually allocated by the kernel: for example, if overcommit is enabled on Linux, the memory may not be available when its use is attempted.

Stabilized APIs

The following methods and trait implementations were stabilized.

The following previously stable functions are now const.

Other changes

There are other changes in the Rust 1.57.0 release: check out what changed inRust,Cargo, and Clippy.

Contributors to 1.57.0

Many people came together to create Rust 1.57.0. We couldn't have done it without all of you.Thanks!

Continue Reading…

Rust Blog

Announcing Rust 1.56.1

The Rust team has published a new point release of Rust, 1.56.1. 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.56.1 is as easy as:

rustup update stable

If you don't have it already, you can get rustup from the appropriate page on our website.

What's in 1.56.1 stable

Rust 1.56.1 introduces two new lints to mitigate the impact of a security concern recently disclosed, CVE-2021-42574. We recommend all users upgrade immediately to ensure their codebase is not affected by the security issue.

You can learn more about the security issue in the advisory.

Continue Reading…

Rust Blog

Security advisory for rustc (CVE-2021-42574)

This is a cross-post of the official security advisory. The official advisory contains a signed version with our PGP key, as well.

The Rust Security Response WG was notified of a security concern affecting source code containing "bidirectional override" Unicode codepoints: in some cases the use of those codepoints could lead to the reviewed code being different than the compiled code.

This is a vulnerability in the Unicode specification, and its assigned identifier is CVE-2021-42574. While the vulnerability itself is not a rustc flaw, we're taking proactive measures to mitigate its impact on Rust developers.

Overview

Unicode has support for both left-to-right and right-to-left languages, and to aid writing left-to-right words inside a right-to-left sentence (or vice versa) it also features invisible codepoints called "bidirectional override".

These codepoints are normally used across the Internet to embed a word inside a sentence of another language (with a different text direction), but it was reported to us that they could be used to manipulate how source code is displayed in some editors and code review tools, leading to the reviewed code being different than the compiled code. This is especially bad if the whole team relies on bidirectional-aware tooling.

As an example, the following snippet (with {U+NNNN} replaced with the Unicode codepoint NNNN):

if access_level != &quot;user{U+202E} {U+2066}// Check if admin{U+2069} {U+2066}&quot; {

...would be rendered by bidirectional-aware tools as:

if access_level != &quot;user&quot; { // Check if admin

Affected Versions

Rust 1.56.1 introduces two new lints to detect and reject code containing the affected codepoints. Rust 1.0.0 through Rust 1.56.0 do not include such lints, leaving your source code vulnerable to this attack if you do not perform out-of-band checks for the presence of those codepoints.

To assess the security of the ecosystem we analyzed all crate versions ever published on crates.io (as of 2021-10-17), and only 5 crates have the affected codepoints in their source code, with none of the occurrences being malicious.

Mitigations

We will be releasing Rust 1.56.1 today, 2021-11-01, with two new deny-by-default lints detecting the affected codepoints, respectively in string literals and in comments. The lints will prevent source code files containing those codepoints from being compiled, protecting you from the attack.

If your code has legitimate uses for the codepoints we recommend replacing them with the related escape sequence. The error messages will suggest the right escapes to use.

If you can't upgrade your compiler version, or your codebase also includes non-Rust source code files, we recommend periodically checking that the following codepoints are not present in your repository and your dependencies: U+202A, U+202B, U+202C, U+202D, U+202E, U+2066, U+2067, U+2068, U+2069.

Timeline of events

  • 2021-07-25: we received the report and started working on a fix.
  • 2021-09-14: the date for the embargo lift (2021-11-01) is communicated to us.
  • 2021-10-17: performed an analysis of all the source code ever published to
    crates.io to check for the presence of this attack.
  • 2021-11-01: embargo lifts, the vulnerability is disclosed and Rust 1.56.1 is
    released.

Acknowledgments

Thanks to Nicholas Boucher and Ross Anderson from the University of Cambridge for disclosing this to us according to our security policy!

We also want to thank the members of the Rust project who contributed to the mitigations for this issue. Thanks to Esteban Küber for developing the lints, Pietro Albini for leading the security response, and many others for their involvement, insights and feedback: Josh Stone, Josh Triplett, Manish Goregaokar, Mara Bos, Mark Rousskov, Niko Matsakis, and Steve Klabnik.

Appendix: Homoglyph attacks

As part of their research, Nicholas Boucher and Ross Anderson also uncovered a similar security issue identified as CVE-2021-42694 involving homoglyphs inside identifiers. Rust already includes mitigations for that attack since Rust 1.53.0. Rust 1.0.0 through Rust 1.52.1 is not affected due to the lack of support for non-ASCII identifiers in those releases.

Continue Reading…

Rust Blog

Announcing Rust 1.56.0 and Rust 2021

The Rust team is happy to announce a new version of Rust, 1.56.0. This stabilizes the 2021 edition as well. Rust is a programming language empowering everyone to build reliable and efficient software.

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

rustup update stable

If you don't have it already, you can get rustupfrom the appropriate page on our website, and check out thedetailed release notes for 1.56.0 on GitHub.

What's in 1.56.0 stable

Rust 2021

We wrote about plans for the Rust 2021 Edition in May. Editions are a mechanism for opt-in changes that may otherwise pose backwards compatibility risk. See the edition guide for details on how this is achieved. This a smaller edition, especially compared to 2018, but there are still some nice quality-of-life changes that require an edition opt-in to avoid breaking some corner cases in existing code. See the new chapters of the edition guide below for more details on each new feature and guidance for migration.

Disjoint capture in closures

Closures automatically capture values or references to identifiers that are used in the body, but before 2021, they were always captured as a whole. The new disjoint-capture feature will likely simplify the way you write closures, so let's look at a quick example:

// 2015 or 2018 edition code
let a = SomeStruct::new();

// Move out of one field of the struct
drop(a.x);

// Ok: Still use another field of the struct
println!(&quot;{}&quot;, a.y);

// Error: Before 2021 edition, tries to capture all of `a`
let c = || println!(&quot;{}&quot;, a.y);
c();

To fix this, you would have had to extract something like let y = &amp;a.y;manually before the closure to limit its capture. Starting in Rust 2021, closures will automatically capture only the fields that they use, so the above example will compile fine!

This new behavior is only activated in the new edition, since it can change the order in which fields are dropped. As for all edition changes, an automatic migration is available, which will update your closures for which this matters by inserting let _ = &amp;a; inside the closure to force the entire struct to be captured as before.

Migrating to 2021

The guide includes migration instructions for all new features, and in generaltransitioning an existing project to a new edition. In many cases cargo fix can automate the necessary changes. You may even find that no changes in your code are needed at all for 2021!

However small this edition appears on the surface, it's still the product of a lot of hard work from many contributors: see our dedicatedcelebration and thanks tracker!

Cargo rust-version

Cargo.toml now supports a [package]rust-version field to specify the minimum supported Rust version for a crate, and Cargo will exit with an early error if that is not satisfied. This doesn't currently influence the dependency resolver, but the idea is to catch compatibility problems before they turn into cryptic compiler errors.

New bindings in binding @ pattern

Rust pattern matching can be written with a single identifier that binds the entire value, followed by @ and a more refined structural pattern, but this has not allowed additional bindings in that pattern -- until now!

struct Matrix {
    data: Vec&lt;f64&gt;,
    row_len: usize,
}

// Before, we need separate statements to bind
// the whole struct and also read its parts.
let matrix = get_matrix();
let row_len = matrix.row_len;
// or with a destructuring pattern:
let Matrix { row_len, .. } = matrix;

// Rust 1.56 now lets you bind both at once!
let matrix @ Matrix { row_len, .. } = get_matrix();

This actually was allowed in the days before Rust 1.0, but that was removed due to known unsoundness at the time. With the evolution of the borrow checker since that time, and with heavy testing, the compiler team determined that this was safe to finally allow in stable Rust!

Stabilized APIs

The following methods and trait implementations were stabilized.

The following previously stable functions are now const.

Other changes

There are other changes in the Rust 1.56.0 release: check out what changed inRust,Cargo, and Clippy.

Contributors to 1.56.0

Many people came together to create Rust 1.56.0 and the 2021 edition. We couldn't have done it without all of you.Thanks!

Continue Reading…

Rust Blog

Core team membership updates

The Rust Core team is excited to announce the first of a series of changes to its structure we’ve been planning for 2021, starting today by adding several new members.

Originally, the Core team was composed of the leads from each Rust team. However, as Rust has grown, this has long stopped being true; most members of the Core team are not team leads in the project. In part, this is because Core’s duties have evolved significantly away from the original technical focus. Today, we see the Core team’s purpose as enabling, amplifying, and supporting the excellent work of every Rust team. Notably, this included setting up andlaunching the Rust Foundation.

We know that our maintainers, and especially team leads, dedicate an enormous amount of time to their work on Rust. We care deeply that it’s possible for not just people working full time on Rust to be leaders, but that part time volunteers can as well. To enable this, we wish to avoid coupling leading a team with a commitment to stewarding the project as a whole as part of the Core team. Likewise, it is important that members of the Core team have the option to dedicate their time to just the Core team’s activities and serve the project in that capacity only.

Early in the Rust project, composition of the Core team was made up of almost entirely Mozilla employees working full time on Rust. Because this team was made up of team leads, it follows that team leads were also overwhelmingly composed of Mozilla employees. As Rust has grown, folks previously employed at Mozilla left for new jobs and new folks appeared. Many of the new folks were not employed to work on Rust full time so the collective time investment was decreased and the shape of the core team’s work schedule shifted from 9-5 to a more volunteer cadence. Currently, the Core team is composed largely of volunteers, and no member of the Core team is employed full time to work on their Core team duties.

We know that it’s critical to driving this work successfully to have stakeholders on the team who are actively working in all areas of the project to help prioritize the Core team’s initiatives. To serve this goal, we are announcing some changes to the Core team’s membership today: Ryan Levick, Jan-Erik Rediger, and JT are joining the Core team. To give some context on their backgrounds and experiences, each new member has written up a brief introduction.

  • Ryan Levick began exploring Rust in 2014 always
    looking for more and more ways to be involved in the community. Over time he
    participated more by co-organizing the Berlin Rust meetup, doing YouTube
    tutorials, helping with various project efforts, and more. In 2019, Ryan got
    the opportunity to work with Rust full time leading developer advocacy for
    Rust at Microsoft and helping build up the case for Rust as an official
    language inside of Microsoft. Nowadays he’s an active Rust project member with
    some of the highlights including working in the compiler perf team, running
    the Rust annual survey, and helping the 2021 edition effort.
  • Jan-Erik Rediger started working with Rust
    sometime in late 2014 and has been a member of the Rust Community Team since
    2016. That same year he co-founded RustFest, one of the first conferences
    dedicated to Rust. In the following years seven RustFest conferences have
    brought together hundreds of Rust community members all around Europe and
    more recently online.
  • JT has 15 years of programming language
    experience. During that time, JT worked at Cray on the Chapel programming
    language and at Apple on LLVM/Clang. In 2012, they joined Microsoft as part
    of the TypeScript core team, where they helped to finish and release
    TypeScript to the world. They stayed on for over three years, helping direct
    TypeScript and grow its community. From there, they joined Mozilla to work on
    Rust, where they brought their experience with TypeScript to help the Rust
    project transition from a research language to an industrial language. During
    this time, they co-created the new Rust compiler error message format and the
    Rust Language Server. Their most recent work is with Nushell, a programming
    language implemented in Rust.

These new additions will add fresh perspectives along several axes, including geographic and employment diversity. However, we recognize there are aspects of diversity we can continue to improve. We see this work as critical to the ongoing health of the Rust project and is part of the work that will be coordinated between the Rust core team and the Rust Foundation.

Manish Goregaokar is also leaving the team to be able to focus better on the dev-tools team. Combining team leadership with Core team duties is a heavy burden. While Manish has enjoyed his time working on project-wide initiatives, this coupling isn’t quite fair to the needs of the devtools team, and he’s glad to be able to spend more time on the devtools team moving forward.

The Core team has been doing a lot of work in figuring out how to improve how we work and how we interface with the rest of the project. We’re excited to be able to share more on this in future updates.

We're super excited for Manish’s renewed efforts on the dev tools team and for JT, Ryan, and Jan-Erik to get started on core team work! Congrats and good luck!

This post is part 1 of a multi-part series on updates to the Rust core team.

Continue Reading…

Rust Blog

Announcing Rust 1.55.0

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

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

rustup update stable

If you don't have it already, you can get rustupfrom the appropriate page on our website, and check out thedetailed release notes for 1.55.0 on GitHub.

What's in 1.55.0 stable

Cargo deduplicates compiler errors

In past releases, when running cargo test, cargo check --all-targets, or similar commands which built the same Rust crate in multiple configurations, errors and warnings could show up duplicated as the rustc's were run in parallel and both showed the same warning.

For example, in 1.54.0, output like this was common:

$ cargo +1.54.0 check --all-targets
    Checking foo v0.1.0
warning: function is never used: `foo`
 --&gt; src/lib.rs:9:4
  |
9 | fn foo() {}
  |    ^^^
  |
  = note: `#[warn(dead_code)]` on by default

warning: 1 warning emitted

warning: function is never used: `foo`
 --&gt; src/lib.rs:9:4
  |
9 | fn foo() {}
  |    ^^^
  |
  = note: `#[warn(dead_code)]` on by default

warning: 1 warning emitted

    Finished dev [unoptimized + debuginfo] target(s) in 0.10s

In 1.55, this behavior has been adjusted to deduplicate and print a report at the end of compilation:

$ cargo +1.55.0 check --all-targets
    Checking foo v0.1.0
warning: function is never used: `foo`
 --&gt; src/lib.rs:9:4
  |
9 | fn foo() {}
  |    ^^^
  |
  = note: `#[warn(dead_code)]` on by default

warning: `foo` (lib) generated 1 warning
warning: `foo` (lib test) generated 1 warning (1 duplicate)
    Finished dev [unoptimized + debuginfo] target(s) in 0.84s

Faster, more correct float parsing

The standard library's implementation of float parsing has been updated to use the Eisel-Lemire algorithm, which brings both speed improvements and improved correctness. In the past, certain edge cases failed to parse, and this has now been fixed.

You can read more details on the new implementation in the pull request description.

std::io::ErrorKind variants updated

std::io::ErrorKind is a #[non_exhaustive] enum that classifies errors into portable categories, such as NotFound or WouldBlock. Rust code that has a std::io::Error can call the kind method to obtain a std::io::ErrorKind and match on that to handle a specific error.

Not all errors are categorized into ErrorKind values; some are left uncategorized and placed in a catch-all variant. In previous versions of Rust, uncategorized errors used ErrorKind::Other; however, user-created std::io::Error values also commonly used ErrorKind::Other. In 1.55, uncategorized errors now use the internal variant ErrorKind::Uncategorized, which we intend to leave hidden and never available for stable Rust code to name explicitly; this leaves ErrorKind::Other exclusively for constructing std::io::Error values that don't come from the standard library. This enforces the #[non_exhaustive] nature of ErrorKind.

Rust code should never match ErrorKind::Other and expect any particular underlying error code; only match ErrorKind::Other if you're catching a constructed std::io::Error that uses that error kind. Rust code matching on std::io::Error should always use _ for any error kinds it doesn't know about, in which case it can match the underlying error code, or report the error, or bubble it up to calling code.

We're making this change to smooth the way for introducing new ErrorKind variants in the future; those new variants will start out nightly-only, and only become stable later. This change ensures that code matching variants it doesn't know about must use a catch-all _ pattern, which will work both with ErrorKind::Uncategorized and with future nightly-only variants.

Open range patterns added

Rust 1.55 stabilized using open ranges in patterns:

match x as u32 {
      0 =&gt; println!(&quot;zero!&quot;),
      1.. =&gt; println!(&quot;positive number!&quot;),
}

Read more details here.

Stabilized APIs

The following methods and trait implementations were stabilized.

The following previously stable functions are now const.

Other changes

There are other changes in the Rust 1.55.0 release: check out what changed in Rust, Cargo, and Clippy.

Contributors to 1.55.0

Many people came together to create Rust 1.55.0. We couldn't have done it without all of you.Thanks!

Dedication

Anna Harren was a member of the community and contributor to Rust known for coining the term "Turbofish" to describe ::&lt;&gt; syntax. Anna recently passed away after living with cancer. Her contribution will forever be remembered and be part of the language, and we dedicate this release to her memory.

Continue Reading…

Rust Blog

The push for GATs stabilization

The push for GATs stabilization

Where to start, where to start...

Let's begin by saying: this is a very exciting post. Some people reading this will be overwhelmingly thrilled; some will have no idea what GATs (generic associated types) are; others might be in disbelief. The RFC for this feature did get opened in April of 2016 (and merged about a year and a half later). In fact, this RFC even predates const generics (which an MVP of was recently stabilized). Don't let this fool you though: it is a powerful feature; and the reactions to the tracking issue on Github should maybe give you an idea of its popularity (it is the most upvoted issue on the Rust repository):GATs reactions

If you're not familiar with GATs, they allow you to define type, lifetime, or const generics on associated types. Like so:

trait Foo {
    type Bar&lt;'a&gt;;
}

Now, this may seem underwhelming, but I'll go into more detail later as to why this really is a powerful feature.

But for now: what exactly is happening? Well, nearly four years after its RFC was merged, the generic_associated_types feature is no longer "incomplete."

crickets chirping

Wait...that's it?? Well, yes! I'll go into a bit of detail later in this blog post as to why this is a big deal. But, long story short, there have been a good amount of changes that have had to have been made to the compiler to get GATs to work. And, while there are still a few small remaining diagnostics issues, the feature is finally in a space that we feel comfortable making it no longer "incomplete".

So, what does that mean? Well, all it really means is that when you use this feature on nightly, you'll no longer get the "generic_associated_types is incomplete" warning. However, the real reason this is a big deal: we want to stabilize this feature. But we need your help. We need you to test this feature, to file issues for any bugs you find or for potential diagnostic improvements. Also, we'd love for you to just tell us about some interesting patterns that GATs enable over on Zulip!

Without making promises that we aren't 100% sure we can keep, we have high hopes we can stabilize this feature within the next couple months. But, we want to make sure we aren't missing glaringly obvious bugs or flaws. We want this to be a smooth stabilization.

Okay. Phew. That's the main point of this post and the most exciting news. But as I said before, I think it's also reasonable for me to explain what this feature is, what you can do with it, and some of the background and how we got here.

So what are GATs?

Note: this will only be a brief overview. The RFC contains many more details.

GATs (generic associated types) were originally proposed in RFC 1598. As said before, they allow you to define type, lifetime, or const generics on associated types. If you're familiar with languages that have "higher-kinded types", then you could call GATs type constructors on traits. Perhaps the easiest way for you to get a sense of how you might use GATs is to jump into an example.

Here is a popular use case: a LendingIterator (formerly known as a StreamingIterator):

trait LendingIterator {
    type Item&lt;'a&gt; where Self: 'a;

    fn next&lt;'a&gt;(&amp;'a mut self) -&gt; Option&lt;Self::Item&lt;'a&gt;&gt;;
}

Let's go through one implementation of this, a hypothetical &lt;[T]&gt;::windows_mut, which allows for iterating through overlapping mutable windows on a slice. If you were to try to implement this with Iterator today like

struct WindowsMut&lt;'t, T&gt; {
    slice: &amp;'t mut [T],
    start: usize,
    window_size: usize,
}

impl&lt;'t, T&gt; Iterator for WindowsMut&lt;'t, T&gt; {
    type Item = &amp;'t mut [T];

    fn next&lt;'a&gt;(&amp;'a mut self) -&gt; Option&lt;Self::Item&gt; {
        let retval = self.slice[self.start..].get_mut(..self.window_size)?;
        self.start += 1;
        Some(retval)
    }
}

then you would get an error.

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --&gt; src/lib.rs:9:22
   |
9  |         let retval = self.slice[self.start..].get_mut(..self.window_size)?;
   |                      ^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the method body at 8:13...
  --&gt; src/lib.rs:8:13
   |
8  |     fn next&lt;'a&gt;(&amp;'a mut self) -&gt; Option&lt;Self::Item&gt; {
   |             ^^
note: ...so that reference does not outlive borrowed content
  --&gt; src/lib.rs:9:22
   |
9  |         let retval = self.slice[self.start..].get_mut(..self.window_size)?;
   |                      ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'t` as defined on the impl at 6:6...
  --&gt; src/lib.rs:6:6
   |
6  | impl&lt;'t, T: 't&gt; Iterator for WindowsMut&lt;'t, T&gt; {
   |      ^^

Put succinctly, this error is essentially telling us that in order for us to be able to return a reference to self.slice, it must live as long as 'a, which would require a 'a: 't bound (which we can't provide). Without this, we could call next while already holding a reference to the slice, creating overlapping mutable references. However, it does compile fine if you were to implement this using the LendingIterator trait from before:

impl&lt;'t, T&gt; LendingIterator for WindowsMut&lt;'t, T&gt; {
    type Item&lt;'a&gt; where Self: 'a = &amp;'a mut [T];

    fn next&lt;'a&gt;(&amp;'a mut self) -&gt; Option&lt;Self::Item&lt;'a&gt;&gt; {
        let retval = self.slice[self.start..].get_mut(..self.window_size)?;
        self.start += 1;
        Some(retval)
    }
}

As an aside, there's one thing to note about this trait and impl that you might be curious about: the where Self: 'a clause on Item. Briefly, this allows us to use &amp;'a mut [T]; without this where clause, someone could try to return Self::Item&lt;'static&gt; and extend the lifetime of the slice. We understand that this is a point of confusion sometimes and are considering potential alternatives, such as always assuming this bound or implying it based on usage within the trait (see this issue). We definitely would love to hear about your use cases here, particularly when assuming this bound would be a hindrance.

As another example, imagine you wanted a struct to be generic over a pointer to a specific type. You might write the following code:

trait PointerFamily {
    type Pointer&lt;T&gt;: Deref&lt;Target = T&gt;;

    fn new&lt;T&gt;(value: T) -&gt; Self::Pointer&lt;T&gt;;
}

struct ArcFamily;
struct RcFamily;

impl PointerFamily for ArcFamily {
    type Pointer&lt;T&gt; = Arc&lt;T&gt;;
    ...
}
impl PointerFamily for RcFamily {
    type Pointer&lt;T&gt; = Rc&lt;T&gt;;
    ...
}

struct MyStruct&lt;P: PointerFamily&gt; {
    pointer: P::Pointer&lt;String&gt;,
}

We won't go in-depth on the details here, but this example is nice in that it not only highlights the use of types in GATs, but also shows that you can still use the trait bounds that you already can use on associated types.

These two examples only scratch the surface of the patterns that GATs support. If you find any that seem particularly interesting or clever, we would love to hear about them over on Zulip!

Why has it taken so long to implement this?

So what has caused us to have taken nearly four years to get to the point that we are now? Well, it's hard to put into words how much the existing trait solver has had to change and adapt; but, consider this: for a while, it was thought that to support GATs, we would have to transition rustc to use Chalk, a potential future trait solver that uses logical predicates to solve trait goals (though, while some progress has been made, it's still very experimental even now).

For reference, here are some various implementation additions and changes that have been made that have furthered GAT support in some way or another:

  • Parsing GATs in AST (#45904)
  • Resolving lifetimes in GATs (#46706)
  • Initial trait solver work to support lifetimes (#67160)
  • Validating projection bounds (and making changes that allow type and const GATs) (#72788)
  • Separating projection bounds and predicates (#73905)
  • Allowing GATs in trait paths (#79554)
  • Partially replace leak check with universes (#65232)
  • Move leak check to later in trait solving (#72493)
  • Replacing bound vars in GATs with placeholders when projecting (#86993)

And to further emphasize the work above: many of these PRs are large and have considerable design work behind them. There are also several smaller PRs along the way. But, we made it. And I just want to congratulate everyone who's put effort into this one way or another. You rock.

What limitations are there currently?

Ok, so now comes the part that nobody likes hearing about: the limitations. Fortunately, in this case, there's really only one GAT limitation: traits with GATs are not object safe. This means you won't be able to do something like

fn takes_iter(_: &amp;mut dyn for&lt;'a&gt; LendingIterator&lt;Item&lt;'a&gt; = &amp;'a i32&gt;) {}

The biggest reason for this decision is that there's still a bit of design and implementation work to actually make this usable. And while this is a nice feature, adding this in the future would be a backward-compatible change. We feel that it's better to get most of GATs stabilized and then come back and try to tackle this later than to block GATs for even longer. Also, GATs without object safety are still very powerful, so we don't lose much by defering this.

As was mentioned earlier in this post, there are still a couple remaining diagnostics issues. If you do find bugs though, please file issues!

Continue Reading…