Rust Blog: Posts

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!("...")), or with a single &str interpolated value (panic!("{}", 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::<u64>() == 8);
const _: () = assert!(std::mem::size_of::<u8>() == 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 = "release"
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 != "user{U+202E} {U+2066}// Check if admin{U+2069} {U+2066}" {

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

if access_level != "user" { // 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!("{}", a.y);

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

To fix this, you would have had to extract something like let y = &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 _ = &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<f64>,
    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`
 --> 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`
 --> 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`
 --> 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 => println!("zero!"),
      1.. => println!("positive number!"),
}

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 ::<> 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<'a>;
}

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<'a> where Self: 'a;

    fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
}

Let's go through one implementation of this, a hypothetical <[T]>::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<'t, T> {
    slice: &'t mut [T],
    start: usize,
    window_size: usize,
}

impl<'t, T> Iterator for WindowsMut<'t, T> {
    type Item = &'t mut [T];

    fn next<'a>(&'a mut self) -> Option<Self::Item> {
        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
  --> 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...
  --> src/lib.rs:8:13
   |
8  |     fn next<'a>(&'a mut self) -> Option<Self::Item> {
   |             ^^
note: ...so that reference does not outlive borrowed content
  --> 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...
  --> src/lib.rs:6:6
   |
6  | impl<'t, T: 't> Iterator for WindowsMut<'t, T> {
   |      ^^

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<'t, T> LendingIterator for WindowsMut<'t, T> {
    type Item<'a> where Self: 'a = &'a mut [T];

    fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> {
        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 &'a mut [T]; without this where clause, someone could try to return Self::Item<'static> 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<T>: Deref<Target = T>;

    fn new<T>(value: T) -> Self::Pointer<T>;
}

struct ArcFamily;
struct RcFamily;

impl PointerFamily for ArcFamily {
    type Pointer<T> = Arc<T>;
    ...
}
impl PointerFamily for RcFamily {
    type Pointer<T> = Rc<T>;
    ...
}

struct MyStruct<P: PointerFamily> {
    pointer: P::Pointer<String>,
}

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(_: &mut dyn for<'a> LendingIterator<Item<'a> = &'a i32>) {}

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…

Rust Blog

Announcing Rust 1.54.0

The Rust team is happy to announce a new version of Rust, 1.54.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.54.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.54.0 on GitHub.

What's in 1.54.0 stable

Attributes can invoke function-like macros

Rust 1.54 supports invoking function-like macros inside attributes. Function-like macros can be either macro_rules! based or procedural macros which are invoked like macro!(...). One notable use case for this is including documentation from other files into Rust doc comments. For example, if your project's README represents a good documentation comment, you can use include_str! to directly incorporate the contents. Previously, various workarounds allowed similar functionality, but from 1.54 this is much more ergonomic.

#![doc = include_str!("README.md")]

Macros can be nested inside the attribute as well, for example to include content generated by a build script:

#[path = concat!(env!("OUT_DIR"), "/generated.rs")]
mod generated;

Read here for more details.

wasm32 intrinsics stabilized

A number of intrinsics for the wasm32 platform have been stabilized, which gives access to the SIMD instructions in WebAssembly.

Notably, unlike the previously stabilized x86 and x86_64 intrinsics, these do not have a safety requirement to only be called when the appropriate target feature is enabled. This is because WebAssembly was written from the start to validate code safely before executing it, so instructions are guaranteed to be decoded correctly (or not at all).

This means that we can expose some of the intrinsics as entirely safe functions, for example v128_bitselect. However, there are still some intrinsics which are unsafe because they use raw pointers, such as v128_load.

Incremental Compilation is re-enabled by default

Incremental compilation has been re-enabled by default in this release, after it being disabled by default in 1.52.1.

In Rust 1.52, additional validation was added when loading incremental compilation data from the on-disk cache. This resulted in a number of pre-existing potential soundness issues being uncovered as the validation changed these silent bugs into internal compiler errors (ICEs). In response, the Compiler Team decided to disable incremental compilation in the 1.52.1 patch, allowing users to avoid encountering the ICEs and the underlying unsoundness, at the expense of longer compile times. 1

Since then, we've conducted a series of retrospectives and contributors have been hard at work resolving the reported issues, with some fixes landing in 1.53 and the majority landing in this release. 2

There are currently still two known issues which can result in an ICE. Due to the lack of automated crash reporting, we can't be certain of the full extent of impact of the outstanding issues. However, based on the feedback we received from users affected by the 1.52 release, we believe the remaining issues to be rare in practice.

Therefore, incremental compilation has been re-enabled in this release!

Stabilized APIs

The following methods and trait implementations were stabilized.

Other changes

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

rustfmt has also been fixed in the 1.54.0 release to properly format nested out-of-line modules. This may cause changes in formatting to files that were being ignored by the 1.53.0 rustfmt. See details here.

Contributors to 1.54.0

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

  1. The 1.52.1 release notes contain a more detailed description of these events.
  2. The tracking issue for the issues is #84970.

Continue Reading…

Rust Blog

Rust 2021 public testing period

Rust 2021 public testing period

We are happy to announce that the Rust 2021 edition is entering its public testing period. All of the planned features for the edition are now available on nightly builds along with migrations that should move your code from Rust 2018 to Rust 2021. If you'd like to learn more about the changes that are part of Rust 2021, check out the nightly version of the Edition Guide.

Public testing period

As we enter the public testing period, we are encouraging adventurous users to test migrating their crates over to Rust 2021. As always, we expect this to be a largely automated process. The steps to try out the Rust 2021 Edition as follows (more detailed directions can be found here):

  1. Install the most recent nightly: rustup update nightly.
  2. Run cargo +nightly fix --edition.
  3. Edit Cargo.toml and place cargo-features = ["edition2021"] at the top (above [package]), and change the edition field to say edition = "2021".
  4. Run cargo +nightly check to verify it now works in the new edition.

Note that Rust 2021 is still unstable, so you can expect bugs and other changes! We recommend migrating your crates in a temporary copy of your code versus your main branch. If you do encounter problems, or find areas where quality could be improved (missing documentation, confusing error messages, etc) please file an issue and tell us about it! Thank you!

What comes next

We are targeting stabilization of all Rust 2021 for Rust 1.56, which will be released on October 21st, 2021. Per the Rust train release model, that means all features and work must be landed on nightly by September 7th.

Continue Reading…

Rust Blog

Rust Blog updated their profile.

Rust Blog

Announcing Rust 1.53.0

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

If you have a previous version of Rust installed via rustup, getting Rust 1.53.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.53.0 on GitHub.

What's in 1.53.0 stable

This release contains several new language features and many new library features, including the long-awaited IntoIterator implementation for arrays. See the detailed release notesto learn about other changes not covered by this post.

IntoIterator for arrays

This is the first Rust release in which arrays implement the IntoIterator trait. This means you can now iterate over arrays by value:

for i in [1, 2, 3] {
    ..
}

Previously, this was only possible by reference, using &[1, 2, 3] or [1, 2, 3].iter().

Similarly, you can now pass arrays to methods expecting a T: IntoIterator:

let set = BTreeSet::from_iter([1, 2, 3]);
for (a, b) in some_iterator.chain([1]).zip([1, 2, 3]) {
    ..
}

This was not implemented before, due to backwards compatibility problems. Because IntoIterator was already implemented for references to arrays,array.into_iter() already compiled in earlier versions, resolving to (&array).into_iter().

As of this release, arrays implement IntoIterator with a small workaround to avoid breaking code. The compiler will continue to resolve array.into_iter() to (&array).into_iter(), as if the trait implementation does not exist. This only applies to the .into_iter() method call syntax, and does not affect any other syntax such as for e in [1, 2, 3], iter.zip([1, 2, 3]) orIntoIterator::into_iter([1, 2, 3]), which all compile fine.

Since this special case for .into_iter() is only required to avoid breaking existing code, it is removed in the new edition, Rust 2021, which will be released later this year. See the edition announcementfor more information.

Or patterns

Pattern syntax has been extended to support | nested anywhere in the pattern. This enables you to write Some(1 | 2) instead of Some(1) | Some(2).

match result {
     Ok(Some(1 | 2)) => { .. }
     Err(MyError { kind: FileNotFound | PermissionDenied, .. }) => { .. }
     _ => { .. }
}

Unicode identifiers

Identifiers can now contain non-ascii characters. All valid identifier characters in Unicode as defined in UAX #31 can now be used. That includes characters from many different scripts and languages, but does not include emoji.

For example:

const BLÅHAJ: &str = "🦈";

struct 人 {
    名字: String,
}

let α = 1;

The compiler will warn about potentially confusing situations involving different scripts. For example, using identifiers that look very similar will result in a warning.

warning: identifier pair considered confusable between `s` and `s`

HEAD branch name support in Cargo

Cargo no longer assumes the default HEAD of git repositories is named master. This means you no longer need to specify branch = "main" for git dependencies from a repository where the default branch is called main.

Incremental Compilation remains off by default

As previously discussed on the blog post for version 1.52.1, incremental compilation has been turned off by default on the stable Rust release channel. The feature remains available on the beta and nightly release channels. For the 1.53.0 stable release, the method for reenabling incremental is unchanged from 1.52.1.

Stabilized APIs

The following methods and trait implementations were stabilized.

Other changes

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

Contributors to 1.53.0

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

Continue Reading…

Rust Blog

Announcing Rustup 1.24.3

The rustup working group is happy to announce the release of rustup version 1.24.3. 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.24.3 is as easy as 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.24.3

This patch release focusses around resolving some regressions in behaviour in the 1.24.x series, in either low tier platforms, or unusual situations around very old toolchains.

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.24.3 possible!

  • Alexander (asv7c2)
  • Ian Jackson
  • pierwill
  • 二手掉包工程师 (hi-rustin)
  • Robert Collins
  • Daniel Silverstone

Continue Reading…

Rust Blog

Announcing Rustup 1.24.2

The rustup working group is happy to announce the release of rustup version 1.24.2. 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.24.2 is as easy as 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.24.2

1.24.2 introduces pooled allocations to prevent memory fragmentation issues on some platforms with 1.24.x. We're not entirely sure what aspect of the streamed unpacking logic caused allocator fragmentation, but memory pools are a well known fix that should solve this for all platforms.

Those who were encountering CI issues with 1.24.1 should find them resolved.

Other changes

You can check out all the changes to Rustup for 1.24.2 in the changelog!

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

Finally, the Rustup working group are pleased to welcome a new member. Between 1.24.1 and 1.24.2 二手掉包工程师 (hi-rustin) has joined, having already made some excellent contributions.

Thanks

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

  • Carol (Nichols || Goulding)
  • Daniel Silverstone
  • João Marcos Bezerra
  • Josh Rotenberg
  • Joshua Nelson
  • Martijn Gribnau
  • pierwill
  • Robert Collins
  • 二手掉包工程师 (hi-rustin)

Continue Reading…

Rust Blog

Six Years of Rust

Today marks Rust's sixth birthday since it went 1.0 in 2015. A lot has changed since then and especially over the past year, and Rust was no different. In 2020, there was no foundation yet, no const generics, and a lot of organisations were still wondering whether Rust was production ready.

In the midst of the COVID-19 pandemic, hundreds of Rust's global distributed set of team members and volunteers shipped over nine new stable releases of Rust, in addition to various bugfix releases. Today, "Rust in production" isn't a question, but a statement. The newly founded Rust foundation has several members who value using Rust in production enough to help continue to support and contribute to its open development ecosystem.

We wanted to take today to look back at some of the major improvements over the past year, how the community has been using Rust in production, and finally look ahead at some of the work that is currently ongoing to improve and use Rust for small and large scale projects over the next year. Let's get started!

Recent Additions

The Rust language has improved tremendously in the past year, gaining a lot of quality of life features, that while they don't fundamentally change the language, they help make using and maintaining Rust in more places even easier.

  • As of Rust 1.52.0 and the upgrade to LLVM 12, one of few cases of unsoundness around forward progress (such as handling infinite loops) has finally been resolved. This has been a long running collaboration between the Rust teams and the LLVM project, and is a great example of improvements to Rust also benefitting the wider ecosystem of programming languages.
  • On supporting an even wider ecosystem, the introduction of Tier 1 support for 64 bit ARM Linux, and Tier 2 support for ARM macOS & ARM Windows, has made Rust an even better place to easily build your projects across new and different architectures.
  • The most notable exception to the theme of polish has been the major improvements to Rust's compile-time capabilities. The stabilisation of const generics for primitive types, the addition of control flow for const fns, and allowing procedural macros to be used in more places, have allowed completely powerful new types of APIs and crates to be created.

Rustc wasn't the only tool that had significant improvements.

  • Cargo just recently stabilised its new feature resolver, that makes it easier to use your dependencies across different targets.
  • Rustdoc stabilised its "intra-doc links" feature, allowing you to easily and automatically cross reference Rust types and functions in your documentation.
  • Clippy with Cargo now uses a separate build cache that provides much more consistent behaviour.

Rust In Production

Each year Rust's growth and adoption in the community and industry has been unbelievable, and this past year has been no exception. Once again in 2020, Rust was voted StackOverflow's Most Loved Programming Language. Thank you to everyone in the community for your support, and help making Rust what it is today.

With the formation of the Rust foundation, Rust has been in a better position to build a sustainable open source ecosystem empowering everyone to build reliable and efficient software. A number of companies that use Rust have formed teams dedicated to maintaining and improving the Rust project, including AWS, Facebook, and Microsoft.

And it isn't just Rust that has been getting bigger. Larger and larger companies have been adopting Rust in their projects and offering officially supported Rust APIs.

  • Both Microsoft and Amazon have just recently announced and released their new officially supported Rust libraries for interacting with Windows and AWS. Official first party support for these massive APIs helps make Rust people's first choice when deciding what to use for their project.
  • The cURL project has released new versions that offer opt-in support for using Rust libraries for handling HTTP/s and TLS communication. This has been a huge inter-community collaboration between the ISRG, the Hyper & Rustls teams, and the cURL project, and we'd like to thank everyone for their hard work in providing new memory safe backends for a project as massive and widely used as cURL!
  • Tokio (an asynchronous runtime written in Rust), released its 1.0 version and announced their three year stability guarantee, providing everyone with a solid, stable foundation for writing reliable network applications without compromising speed.

Future Work

Of course, all that is just to start, we're seeing more and more initiatives putting Rust in exciting new places;

Right now the Rust teams are planning and coordinating the 2021 edition of Rust. Much like this past year, a lot of themes of the changes are around improving quality of life. You can check out our recent post about "The Plan for the Rust 2021 Edition" to see what the changes the teams are planning.

And that's just the tip of the iceberg; there are a lot more changes being worked on, and exciting new open projects being started every day in Rust. We can't wait to see what you all build in the year ahead!


Are there changes, or projects from the past year that you're excited about? Are you looking to get started with Rust? Do you want to help contribute to the 2021 edition? Then come on over, introduce yourself, and join the discussion over on our Discourse forum and Zulip chat! Everyone is welcome, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, disability, ethnicity, religion, or similar personal characteristic.

Continue Reading…

Rust Blog

The Plan for the Rust 2021 Edition

We are happy to announce that the third edition of the Rust language, Rust 2021, is scheduled for release in October. Rust 2021 contains a number of small changes that are nonetheless expected to make a significant improvement to how Rust feels in practice.

What is an Edition?

The release of Rust 1.0 established"stability without stagnation"as a core Rust deliverable. Ever since the 1.0 release, the rule for Rust has been that once a feature has been released on stable, we are committed to supporting that feature for all future releases.

There are times, however, when it is useful to be able to make small changes to the language that are not backwards compatible. The most obvious example is introducing a new keyword, which would invalidate variables with the same name. For example, the first version of Rust did not have the async and await keywords. Suddenly changing those words to keywords in a later version would've broken code like let async = 1;.

Editions are the mechanism we use to solve this problem. When we want to release a feature that would otherwise be backwards incompatible, we do so as part of a new Rust edition. Editions are opt-in, and so existing crates do not see these changes until they explicitly migrate over to the new edition. This means that even the latest version of Rust will still not treat async as a keyword, unless edition 2018 or later is chosen. This choice is made per crateas part of its Cargo.toml. New crates created by cargo new are always configured to use the latest stable edition.

Editions do not split the ecosystem

The most important rule for editions is that crates in one edition can interoperate seamlessly with crates compiled in other editions. This ensures that the decision to migrate to a newer edition is a "private one" that the crate can make without affecting others.

The requirement for crate interoperability implies some limits on the kinds of changes that we can make in an edition. In general, changes that occur in an edition tend to be "skin deep". All Rust code, regardless of edition, is ultimately compiled to the same internal representation within the compiler.

Edition migration is easy and largely automated

Our goal is to make it easy for crates to upgrade to a new edition. When we release a new edition, we also provide tooling to automate the migration. It makes minor changes to your code necessary to make it compatible with the new edition. For example, when migrating to Rust 2018, it changes anything named async to use the equivalentraw identifier syntax: r#async.

The automated migrations are not necessarily perfect: there might be some corner cases where manual changes are still required. The tooling tries hard to avoid changes to semantics that could affect the correctness or performance of the code.

In addition to tooling, we also maintain an Edition Migration Guide that covers the changes that are part of an edition. This guide will describe the change and give pointers to where people can learn more about it. It will also cover any corner cases or details that people should be aware of. The guide serves both as an overview of the edition, but also as a quick troubleshooting reference if people encounter problems with the automated tooling.

What changes are planned for Rust 2021?

Over the last few months, the Rust 2021 Working Group has gone through a number of proposals for what to include in the new edition. We are happy to announce the final list of edition changes. Each feature had to meet two criteria to make this list. First, they had to be approved by the appropriate Rust team(s). Second, their implementation had to be far enough along that we had confidence that they would be completed in time for the planned milestones.

Additions to the prelude

The prelude of the standard libraryis the module containing everything that is automatically imported in every module. It contains commonly used items such as Option, Vec, drop, and Clone.

The Rust compiler prioritizes any manually imported items over those from the prelude, to make sure additions to the prelude will not break any existing code. For example, if you have a crate or module called example containing a pub struct Option;, then use example::*; will make Option unambiguously refer to the one from example; not the one from the standard library.

However, adding a trait to the prelude can break existing code in a subtle way. A call to x.try_into() using a MyTryInto trait might become ambiguous and fail to compile if std's TryInto is also imported, since it provides a method with the same name. This is the reason we haven't added TryInto to the prelude yet, since there is a lot of code that would break this way.

As a solution, Rust 2021 will use a new prelude. It's identical to the current one, except for three new additions:

Default Cargo feature resolver

Since Rust 1.51.0, Cargo has opt-in support for a new feature resolverwhich can be activated with resolver = "2" in Cargo.toml.

Starting in Rust 2021, this will be the default. That is, writing edition = "2021" in Cargo.toml will imply resolver = "2".

The new feature resolver no longer merges all requested features for crates that are depended on in multiple ways. See the announcement of Rust 1.51 for details.

IntoIterator for arrays

Until Rust 1.53, only references to arrays implement IntoIterator. This means you can iterate over &[1, 2, 3] and &mut [1, 2, 3], but not over [1, 2, 3] directly.

for &e in &[1, 2, 3] {} // Ok :)

for e in [1, 2, 3] {} // Error :(

This has been a long-standing issue, but the solution is not as simple as it seems. Just adding the trait implementation would break existing code.array.into_iter() already compiles today because that implicitly calls(&array).into_iter() due to how method call syntax works. Adding the trait implementation would change the meaning.

Usually we categorize this type of breakage (adding a trait implementation) 'minor' and acceptable. But in this case there is too much code that would be broken by it.

It has been suggested many times to "only implement IntoIterator for arrays in Rust 2021". However, this is simply not possible. You can't have a trait implementation exist in one edition and not in another, since editions can be mixed.

Instead, we decided to add the trait implementation in all editions (starting in Rust 1.53.0), but add a small hack to avoid breakage until Rust 2021. In Rust 2015 and 2018 code, the compiler will still resolve array.into_iter()to (&array).into_iter() like before, as if the trait implementation does not exist. This only applies to the .into_iter() method call syntax. It does not affect any other syntax such as for e in [1, 2, 3], iter.zip([1, 2, 3]) orIntoIterator::into_iter([1, 2, 3]). Those will start to work in all editions.

While it's a shame that this required a small hack to avoid breakage, we're very happy with how this solution keeps the difference between the editions to an absolute minimum. Since the hack is only present in the older editions, there is no added complexity in the new edition.

Disjoint capture in closures

Closuresautomatically capture anything that you refer to from within their body. For example, || a + 1 automatically captures a reference to a from the surrounding context.

Currently, this applies to whole structs, even when only using one field. For example, || a.x + 1 captures a reference to a and not just a.x. In some situations, this is a problem. When a field of the struct is already borrowed (mutably) or moved out of, the other fields can no longer be used in a closure, since that would capture the whole struct, which is no longer available.

let a = SomeStruct::new();

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

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

let c = || println!("{}", a.y); // Error: Tries to capture all of `a`
c();

Starting in Rust 2021, closures will only capture the fields that they use. So, the above example will compile fine in Rust 2021.

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. It can insert let _ = &a; inside the closure to force the entire struct to be captured as before.

Panic macro consistency

The panic!() macro is one of Rust's most well known macros. However, it has some subtle surprisesthat we can't just change due to backwards compatibility.

panic!("{}", 1); // Ok, panics with the message "1"
panic!("{}"); // Ok, panics with the message "{}"

The panic!() macro only uses string formatting when it's invoked with more than one argument. When invoked with a single argument, it doesn't even look at that argument.

let a = "{";
println!(a); // Error: First argument must be a format string literal
panic!(a); // Ok: The panic macro doesn't care

(It even accepts non-strings such as panic!(123), which is uncommon and rarely useful.)

This will especially be a problem onceimplicit format argumentsare stabilized. That feature will make println!("hello {name}") a short-hand for println!("hello {}", name). However, panic!("hello {name}") would not work as expected, since panic!() doesn't process a single argument as format string.

To avoid that confusing situation, Rust 2021 features a more consistent panic!() macro. The new panic!() macro will no longer accept arbitrary expressions as the only argument. It will, just like println!(), always process the first argument as format string. Since panic!() will no longer accept arbitrary payloads,panic_any()will be the only way to panic with something other than a formatted string.

In addition, core::panic!() and std::panic!() will be identical in Rust 2021. Currently, there are some historical differences between those two, which can be noticable when switching #![no_std] on or off.

Reserving syntax

To make space for some new syntax in the future, we've decided to reserve syntax for prefixed identifiers and literals:prefix#identifier, prefix"string", prefix'c', and prefix#123, where prefix can be any identifier. (Except those that already have a meaning, such as b'…' and r"…".)

This is a breaking change, since macros can currently accept hello"world", which they will see as two separate tokens: hello and "world". The (automatic) fix is simple though. Just insert a space: hello "world".

Other than turning these into a tokenization error,the RFC does not attach a meaning to any prefix yet. Assigning meaning to specific prefixes is left to future proposals, which will—thanks to reserving these prefixes now—not be breaking changes.

These are some new prefixes you might see in the future:

  • f"" as a short-hand for a format string.
    For example, f"hello {name}" as a short-hand for the equivalent format_args!() invocation.
  • c"" or z"" for null-terminated C strings.
  • k#keyword to allow writing keywords that don't exist yet in the current edition.
    For example, while async is not a keyword in edition 2015,
    this prefix would've allowed us to accept k#async as an alternative in edition 2015
    while we waited for edition 2018 to reserve async as a keyword.

Promoting two warnings to hard errors

Two existing lints are becoming hard errors in Rust 2021. These lints will remain warnings in older editions.

  • bare-trait-objects:
    The use of the dyn keyword to identify trait objectswill be mandatory in Rust 2021.
  • ellipsis-inclusive-range-patterns:
    The deprecated ... syntaxfor inclusive range patterns is no longer accepted in Rust 2021.
    It has been superseded by ..=, which is consistent with expressions.

Or patterns in macro_rules

Starting in Rust 1.53.0, patternsare extended to support | nested anywhere in the pattern. This enables you to write Some(1 | 2) instead of Some(1) | Some(2). Since this was simply not allowed before, this is not a breaking change.

However, this change also affects macro_rules macros. Such macros can accept patterns using the :pat fragment specifier. Currently, :pat does not match |, since before Rust 1.53, not all patterns (at all nested levels) could contain a |. Macros that accept patterns like A | B, such as matches!()use something like $($_:pat)|+. Because we don't want to break any existing macros, we did not change the meaning of :pat in Rust 1.53.0 to include |.

Instead, we will make that change as part of Rust 2021. In the new edition, the :pat fragment specifier will match A | B.

Since there are times that one still wishes to match a single pattern variant without |, the fragment specified :pat_param has been added to retain the older behavior. The name refers to its main use case: a pattern in a closure parameter.

What comes next?

Our plan is to have these changes merged and fully tested by September, to make sure the 2021 edition makes it into Rust 1.56.0. Rust 1.56.0 will then be in beta for six weeks, after which it is released as stable on October 21st.

However, note that Rust is a project run by volunteers. We prioritize the personal well-being of everyone working on Rust over any deadlines and expectations we might have set. This could mean delaying the edition a version if necessary, or dropping a feature that turns out to be too difficult or stressful to finish in time.

That said, we are on schedule and many of the difficult problems are already tackled, thanks to all the people contributing to Rust 2021! 💛


You can expect another announcement about the new edition in July. At that point we expect all changes and automatic migrations to be implemented and ready for public testing.

We'll be posting some more details about the process and rejected proposals on the "Inside Rust" blog soon. (Correction: This did not end up happening due to lack of bandwidth)

Continue Reading…

Rust Blog

Announcing Rust 1.52.1

The Rust team has prepared a new release, 1.52.1, working around a bug in incremental compilation which was made into a compiler error in 1.52.0. We recommend all Rust users, including those currently using stable versions prior to 1.52.0, upgrade to 1.52.1 or disable incremental compilation. Guidance on how to do so is available below.

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

rustup update stable

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

Summary

This release works around broken builds on 1.52.0, which are caused by newly added verification. The bugs this verification detects are present in all Rust versions1, and can trigger miscompilations in incremental builds, so downgrading to a prior stable version is not a fix.

Users are encouraged to upgrade to 1.52.1 or disable incremental in their local environment if on a prior version: please see the what you should dosection for details on how to do so.

Incremental compilation is off by default for release builds, so few production builds should be affected (only for users who have opted in).

Miscompilations that can arise from the bugs in incremental compilation generate incorrect code in final artifacts, essentially producing malformed binaries, which means that in theory any behavior is possible. In practice we are currently only aware of one particular known miscompilation, but bugs due to incremental are notoriously hard to track down: users frequently simply rebuild after some light editing if they see unexpected results from their binaries, and this often causes sufficient recompilation to fix the bug(s).

This post is going to:

  1. Explain what the errors look like,
  2. Explain what the check does, at a high level,
  3. Explain how the check is presenting itself in the Rust 1.52.0 release,
  4. Tell you what you should do if you see an unstable fingerprint on your project,
  5. Describe our plans for how the Rust project will address the problems discussed here.

What does the error look like?

The error message looks something like this, with the key piece being the "found unstable fingerprints" text.

thread 'rustc' panicked at 'assertion failed: `(left == right)`
  left: `Some(Fingerprint(4565771098143344972, 7869445775526300234))`,
  right: `Some(Fingerprint(14934403843752251060, 623484215826468126))`: found unstable fingerprints for <massive text describing rustc internals elided>

error: internal compiler error: unexpected panic

note: the compiler unexpectedly panicked. this is a bug.

This is the error caused by the internal consistency check, and as stated in the diagnostic, it yields an "Internal Compiler Error" (or ICE). In other words, it represents a bug in the internals of the Rust compiler itself. In this case, the ICE is revealing a bug in incremental compilation that predates the 1.52.0 release and could result in miscompilation if it had not been caught.

What are fingerprints? Why are we checking them?

The Rust compiler has support for "incremental compilation", which has been described in a 2016 blog post. When incremental compilation is turned on, the compiler breaks the input source into pieces, and tracks how those input pieces influence the final build product. Then, when the inputs change, it detects this and reuses artifacts from previous builds, striving to expend effort solely on building the parts that need to respond to the changes to the input source code.

Fingerprints are part of our architecture for detecting when inputs change. More specifically, a fingerprint (along with some other state to establish context) is a 128-bit value intended to uniquely identify internal values used within the compiler. Some compiler-internal results are stored on disk ("cached") between runs. Fingerprints are used to validate that a newly computed result is unchanged from the cached result. (More details about this are available in the relevant chapter of the rustc dev guide.)

The fingerprint stability check is a safeguard asserting internal consistency of the fingerprints. Sometimes the compiler is forced to rerun a query, and expects that the output is the same as from a prior incremental compilation session. The newly enabled verification checks that the value is indeed as expected, rather than assuming so. In some cases, due to bugs in the compiler's implementation, this was not actually the case.

History

We initially added these fingerprint checks as a tool to use when developing rustc itself, back in 2017. It was solely provided via an unstable-Z flag, only available to nightly and development builds.

More recently, in March, we encountered a miscompilation that led us to turn on verify-ich by default. The Rust compiler team decided it was better to catch fingerprint problems and abort compilation, rather than allow for potential miscompilations (and subsequent misbehavior) to sneak into Rust programmer's binaries.

When we first turned on the fingerprint checks by default, there was a steady stream of issues filed by users of the nightly (and beta) toolchains, and steady progress has been made on identifying fixes, a number of which have already landed.

In the past week, we had started making plans to improve the user-experience, so that the diagnostic issued by the check would do a better job of telling the programmer what to do in response. Unfortunately, this was done under the assumption that the new verification would ship in 1.53, not 1.52.

It turns out verify-ich was turned on in version 1.52.0, which was released recently.

Today's new release, 1.52.1, works around the breakage caused by the newly added verification by temporarily changing the defaults in the Rust compiler to disable incremental unless the user knowingly opts in.

How does this show up

Essentially, for some crates, certain sequences of edit-compile cycles will cause rustc to hit the "unstable fingerprints" ICE. I showed one example at the start of this blog post.

Another recent example looks like this:

thread 'rustc' panicked at 'found unstable fingerprints for predicates_of(<massive text describing rustc internals elided>)', /rustc/.../compiler/rustc_query_system/src/query/plumbing.rs:593:5

They all arise from inconsistencies when comparing the incremental-compilation cache stored on disk against the values computed during a current rustc invocation, which means they all arise from using incremental compilation.

There are several ways that you may have incremental compilation turned on:

  1. You may be building with the dev or testprofiles which default to having incremental compilation enabled.
  2. You may have set the environment variableCARGO_INCREMENTAL=1
  3. You may have enabled the build.incrementalsetting in your Cargo config
  4. You may have enabled the incrementalsetting in your Cargo.toml for a given profile

If your project has not adjusted the defaults, then when running cargo build --release or otherwise in the release profile configuration incremental is disabled on all Rust versions1, and these issues should not affect your release builds.

What should a Rust programmer do in response

The Internal Compiler Error asks you to report a bug, and if you can do so, we still want that information. We want to know about the cases that are failing.

But regardless of whether or not you file a bug, the problem can be worked around on your end by either:

  1. upgrading to 1.52.1, if you have not yet done so (which will disable
    incremental for you), or
  2. deleting your incremental compilation cache (e.g. by running cargo clean), or
  3. forcing incremental compilation to be disabled, by setting CARGO_INCREMENTAL=0 in your environment or build.incremental to false in the config.toml.

We recommend that users of 1.52.0 upgrade to 1.52.1, which disables incremental compilation.

We do not recommend that users of 1.52.0 downgrade to an earlier version of Rust in response to this problem. As noted above, there is at least one instance of a silent miscompilation caused by incremental compilation that was not caught until we added the fingerprint checking.

If a user is willing to deal with the incremental verification ICE's, and wishes to opt back into the 1.52.0 behavior, they may set RUSTC_FORCE_INCREMENTAL to1 in their environment. The Rust compiler will then respect the-Cincremental option passed by Cargo, and things will work as before, though with the added verification. Note that this flag does not enable incremental if it has not already been separately enabled (whether by Cargo or otherwise).

If you are currently using a toolchain prior to 1.52.0, and wish to continue doing so, we recommend that you disable incremental compilation to avoid hitting silent miscompilations.

On all Rust builds since incremental has landed, it has been a major improvement to compile times for many users, and has only improved over time. We acknowledge that the workarounds presented here and recommendations are painful, and will be working hard to ensure the situation is as temporary as possible.

What is the Rust project going to do to fix this

Short-term plan

We have issued 1.52.1 today which:

  • Disables incremental compilation in the Rust compiler (unless asked for by a
    new environment variable, RUSTC_FORCE_INCREMENTAL=1).
  • Improves diagnostic output for the new verification if incremental compilation is enabled,
    indicating how to work around the bugs by purging incremental state or
    disabling incremental.

This is intended to be a mitigation that helps the majority of Rust users have an upgrade path to a safe Rust compiler which does not have the risk of miscompiling their code, but also provide the option for users willing to deal with the errors to do so.

We expect to continue to actively invest in fixing the bugs, and depending on our confidence in the fixes, may issue a 1.52.2 point release which backports those fixes to the stable channel. Users wishing to help us test can use the nightly channel, and report bugs to rust-lang/rust with any ICEs they are seeing.

We are also currently not planning to disable incremental on the beta channel, but this decision has not been firmly committed to. A number of fixes are available on 1.53 beta today, so users who wish to continue using incremental may want to switch to that. Nightly will always have the latest in fixes, of course.

Long-term plan

The long-term plan is to fix the bugs! Incremental compilation is the only realistic way for the Rust compiler to be able to provide a fast edit-compile-run cycle for all of its programmers, and so we need to address all of the issues that have been identified thus far via verify-ich. (There are 32 such issues as of this writing, though many are duplicates.)

We are actively investing in this, and a number of bugs have already been identified and fixed. Depending on the state of the fixes, future stable releases (1.53 and onwards) will likely re-enable incremental compilation.

The Rust teams will also be developing plans to ensure we have better tracking systems in place in the future for bugs, both to prevent situations like this from arising again, but also to further increase the stability of our releases by tracking bugs more accurately as they propagate across channels.

  1. Since incremental was first enabled, which was in Rust 1.24.

Continue Reading…

Rust Blog

Announcing Rust 1.52.0

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

If you have a previous version of Rust installed via rustup, getting Rust 1.52.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.52.0 on GitHub.

What's in 1.52.0 stable

The most significant change in this release is not to the language or standard libraries, but rather an enhancement to tooling support for Clippy.

Previously, running cargo check followed by cargo clippy wouldn't actually run Clippy: the build caching in Cargo didn't differentiate between the two. In 1.52, however, this has been fixed, which means that users will get the expected behavior independent of the order in which they run the two commands.

Stabilized APIs

The following methods were stabilized.

The following previously stable APIs are now const.

Other changes

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

Contributors to 1.52.0

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

Continue Reading…

Rust Blog

Announcing Rustup 1.24.1

The rustup working group is happy to announce the release of rustup version 1.24.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.24.1 is as easy as 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.24.1

Firstly, if you have not read the previous announcement then in brief, 1.24 introduces better support for low memory systems, installs itself into the Add/Remove programs list on Windows, and now supports using rust-toolchain.toml files.

Shortly after publishing the 1.24.0 release of Rustup, we got reports of a regressionpreventing users from running rustfmt and cargo fmt after upgrading to Rustup 1.24.0. To limit the damage we reverted the release to version 1.23.1. The only substantive change between 1.24.0 and 1.24.1 is to correct this regression.

Other changes

You can check out all the changes to Rustup for 1.24.0 and 1.24.1 in the changelog!

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

Thanks

Thanks again to all the contributors who made rustup 1.24.0 and 1.24.1 possible!

  • Alex Chan
  • Aloïs Micard
  • Andrew Norton
  • Avery Harnish
  • chansuke
  • Daniel Alley
  • Daniel Silverstone
  • Eduard Miller
  • Eric Huss
  • est31
  • Gareth Hubball
  • Gurkenglas
  • Jakub Stasiak
  • Joshua Nelson
  • Jubilee (workingjubilee)
  • kellda
  • Michael Cooper
  • Philipp Oppermann
  • Robert Collins
  • SHA Miao
  • skim (sl4m)
  • Tudor Brindus
  • Vasili (3point2)
  • наб (nabijaczleweli)
  • 二手掉包工程师 (hi-rustin)

Continue Reading…

Rust Blog

Announcing Rustup 1.24.0

Shortly after publishing the release we got reports of a regressionpreventing users from running rustfmt and cargo fmt after upgrading to Rustup 1.24.0. To limit the damage we reverted the release to version 1.23.1.

If you have been affected by this issue you can revert to version 1.23.1 by running the following command:

rustup self update

The rustup working group is happy to announce the release of rustup version 1.24.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.24.0 is as easy as 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.24.0

Support of rust-toolchain.toml as a filename for specifying toolchains.

Last year we released a new toml format for the rust-toolchain file. In order to bring Rustup closer into line with Cargo's behaviour around .cargo/config we now support the .toml extension for that file. If you call the toolchain file rust-toolchain.toml then you must use the toml format, rather than the legacy one-line format.

If both rust-toolchain and rust-toolchain.toml are present, then the former will win out over the latter to ensure compatibility between Rustup versions.

Better support for low-memory systems

Rustup's component unpacker has been changed to have a smaller memory footprint when unpacking large components. This should permit users of memory-constrained systems such as some Raspberry Pi systems to install newer Rust toolchains which contain particularly large files.

Better support for Windows Add/Remove programs

Fresh installations of Rustup on Windows will now install themselves into the program list so that you can trigger the uninstallation of Rustup via the Add/Remove programs dialogs similar to any other Windows program.

This will only take effect on installation, so you will need to rerun rustup-init.exe if you want this on your PC.

Other changes

There are more changes in rustup 1.24.0: check them out in the changelog!

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

Thanks

Thanks to all the contributors who made rustup 1.24.0 possible!

  • Alex Chan
  • Aloïs Micard
  • Andrew Norton
  • Avery Harnish
  • chansuke
  • Daniel Alley
  • Daniel Silverstone
  • Eduard Miller
  • Eric Huss
  • est31
  • Gareth Hubball
  • Gurkenglas
  • Jakub Stasiak
  • Joshua Nelson
  • Jubilee (workingjubilee)
  • kellda
  • Michael Cooper
  • Philipp Oppermann
  • Robert Collins
  • SHA Miao
  • skim (sl4m)
  • Tudor Brindus
  • Vasili (3point2)
  • наб (nabijaczleweli)
  • 二手掉包工程师 (hi-rustin)

Continue Reading…

Rust Blog

Brainstorming Async Rust's Shiny Future

On March 18th, we announced the start of the Async Vision Doc process. Since then, we've landed 24 "status quo" stories and we have 4 more stories in open PRs; Ryan Levick and I have also hosted more than ten collaborative writing sessions over the course of the last few weeks, and we have more scheduled for this week.

Now that we have a good base of "status quo" stories, we are starting to imagine what the ✨ "shiny future" ✨ might look like. We want your help! If you have a great idea for Async Rust1, then take a look at the template and open a PR! Alternatively, if you have an idea for a story but would like to discuss it before writing, you can open a "shiny future" issue. Also, we would still love to get more "status quo" stories, so please continue to share those.

When writing "shiny future" stories, the goal is to focus on the experience of Rust's users first and foremost, and not so much on the specific technical details. In fact, you don't even have to know exactly how the experience will be achieved. We have a few years to figure that out, after all. 🚀

Every "shiny future" story is a "retelling" of one or more "status quo" stories. The idea is to replay the same scenario but hopefully with a happier ending, as a result of the improvements we've made. If you don't see a "status quo" story that is right for telling your "shiny future" story, though, that's no problem! Write up your story and we'll figure out the "status quo" story it addresses. There is always the option of writing a new "status quo" story, too; we are still requesting "status quo" and "shiny future" stories, and we will do so right up until the end.

If you'd like to see what a "shiny future" story looks like, we have merged one example, Barbara Makes a Wish. This story describes Barbara's experiences using a nifty new tool that gives her lots of information about the state of her async executor. It is a "retelling" of the "status quo" story Barbara Wants Async Insights.

What is the async vision doc and how does it work?

Here is the idea in a nutshell:

We are launching a collaborative effort to build a shared vision document for Async Rust. Our goal is to engage the entire community in a collective act of the imagination: how can we make the end-to-end experience of using Async I/O not only a pragmatic choice, but a joyful one?

As described in the original announcement, the vision document is structured as a series of "status quo" and "shiny future" stories. Each story describes the experiences of one or more of our four characters as they go about achieving their goals using Async Rust.

The "status quo" stories describe the experiences that users have today. They are an amalgamation of the real experiences of people using Async Rust, as reported to us by interviews, blog posts, and tweets. The goal with these stories is to help us understand and gauge the cumulative impact that problems can have on our users.

The "shiny future" stories describe those some characters achieving those same goals, but looking forward a few years into the future. They are meant to illustrate the experience we are aiming towards, and to give the overall context for the RFCs and other kinds of changes we want to pursue.

The brainstorming period and what comes next

We are currently in the midst of the brainstorming period. This means that we are seeking to collect as many stories -- both about the "status quo" and the "shiny future" -- as we can. The brainstorming period lasts until the end of April. After that, the working group leads are going to merge the remaining stories and get to work drafting a synthesized vision document that incorporates elements of the various stories that have been submitted.

Going forward, we plan to revisit the vision document regularly. We fully expect that some aspects of the "shiny future" stories we write are going to be wrong, sometimes very wrong. We will be regularly returning to the vision document to check how things are going and adjust our trajectory appropriately.

This sounds cool, how can I get involved?

If you'd like to help, we'd love to have you! If you've got an idea for a story, then feel free to create a PR to the wg-async-foundations repository based on one of the following templates:

If you'd like a bit more inspiration, then you can join Ryan Levick and I at one of our vision doc writing sessions. We have more sessions scheduled this week and you can look for announcements from us on twitter or check the #wg-async-foundations stream on the rust-lang Zulip.

  1. Don't be modest. You know you do.

Continue Reading…