Skip to content

Add blog post to introduce disjoint capture in closures #884

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions posts/2021-08-01-disjoint-capture-in-closures.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
layout: post
title: "Introducing Disjoint Capture in Closures"
author: The RFC 2229 working group <https://www.rust-lang.org/governance/teams/compiler#wg-rfc-2229>
---

One of the major features of the [upcoming Rust 2021 Edition](https://blog.rust-lang.org/2021/05/11/edition-2021.html)) is a change to how Rust closures work. This change makes closure captures more precise, eliminating common borrow check errors. As a result, it involves some (minor) changes to Rust semantics, which is why it is tied to the Rust 2021 edition.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally this should be a relative link


Like any Edition migration, we have also created lints that will warn you of upcoming changes and suggest precise edits to preserve the semantics of your code. This blog post will explain the new feature and also tell you how you can try it out today on nightly if you like.


## What are closures?
Closures are anonymous functions you can save in a variable or pass as an argument to other functions. They are referred to as ”lambda functions” in other programming languages.

This is a basic closure that prints "Hello, World!":

```rust
let c = || println!("Hello, World!");
```


Closures can capture variables from the scope they are defined in.
```rust
let my_string = "Hello, World";
let c = || println!("{}", my_string); // closure captures (& my_string)
```


If you're new to Rust and haven't used closures, we recommend you check out the [Rust Book](https://doc.rust-lang.org/book/ch13-01-closures.html) and [Rust by Example](https://doc.rust-lang.org/rust-by-example/fn/closures.html) to learn how to use closures.

For those who would like a quick recap, we recommend reading the [Rust Reference](https://doc.rust-lang.org/reference/types/closure.html).


## What is disjoint capture?

Disjoint capture is the ability of a closure to capture only part of a variable rather than the variable in its entirety (Rust 2018 behavior). The goal with this feature is to unify the semantics of closure captures with those of borrowing and move operations.

Consider a Point `p` with fields `x` and `y` corresponding to the x and y coordinates of the point.

```rust
let p = Point { x: 10, y: 20 };

let c = || println!("{}", p.x);
```

`c` in Rust 2018 will capture `p` completely, but in Rust 2021 it will only capture `p.x`. This now matches what gets borrowed when someone writes `println!("{}", p.x)`.

Disjoint capture was proposed as part of [RFC 2229](https://github.com/rust-lang/rfcs/blob/master/text/2229-capture-disjoint-fields.md), and we suggest reading the RFC to better understand motivations behind the feature.

The precise path that gets captured is typically the full path that is used in the closure, but there are cases where we will only capture a prefix of the path. See this pending PR to the [Rust Reference](https://github.com/rust-lang/reference/blob/d24c4642c8efd26915209558e065a5e670363fc0/src/types/closure.md) for the full details.

The feature also includes (minor) breaking changes to the Rust semantics which are also documented in this pending PR to the [Rust Reference](https://github.com/rust-lang/reference/blob/d24c4642c8efd26915209558e065a5e670363fc0/src/types/closure.md).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe link to the PR rust-lang/reference#1059 instead of a commit, since this commit was force pushed over AFAICT.


## How to use the feature?

Interested in testing this out? You can now try disjoint capture in Rust closures on rust nightly using `#![feature(capture_disjoint_fields)]`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These instructions may be out-of-date now, or at least confusing. #![feature(capture_disjoint_fields)] shows a giant warning that the feature is incomplete and may not be safe to use. However, it is now stable in 2021 which seems like a conflicting message to me.

Also, there is only a few weeks left until this hits stable. Might be worth noting that this will be stable on October 21st.


If you would like to be warned of semantics change that may impact your code, you can follow migration instructions provided in the [2021 Edition Guide](https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html#migration).

## How to submit bugs?

To submit a bug simply [open an issue](https://github.com/rust-lang/rust/issues/new/choose) and tag the RFC 2229 working group using `@rust-lang/wg-rfc-2229`. We hope to create the best experince posible so no issue is too small, even a confusing error messages is worth reporting.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most folks won't be able to tag the working group (you need to be part of the org to ping teams). I think the easiest is to just ask folks to leave a label via rustbot, perhaps?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about we ask users to create issue directly on the 2229 repo? https://github.com/rust-lang/project-rfc-2229. MIght be a bit easier than trying to use rustbot

@nikomatsakis what are your thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm! I think I'd prefer to have people file bugs on rust-lang/rust. I'm not sure what's the best way for people to tag disjoint closures though.