You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/rust-2021/disjoint-capture-in-closures.md
+13-9Lines changed: 13 additions & 9 deletions
Original file line number
Diff line number
Diff line change
@@ -3,7 +3,7 @@
3
3
## Summary
4
4
5
5
-`|| a.x + 1` now captures only `a.x` instead of `a`.
6
-
- This can subtly change the drop order of things, and auto traits usage with closures.
6
+
- This can subtly change the drop order of things and whether auto traits are applied to closures or not.
7
7
8
8
## Details
9
9
@@ -35,7 +35,9 @@ So, the above example will compile fine in Rust 2021.
35
35
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.
36
36
37
37
## Changes to semantics because of disjoint capture
38
-
`#[feature(capture_disjoint_fields)]` introduces (minor) breaking change to the language. This means that there might be observable changes or valid Rust 2018 code that fails to compile once you move to Rust Edition 2021. You can use `cargo fix` with the `disjoint_capture_migrations` lint to migrate your existing code to Rust 2021.
38
+
Disjoint captures introduces a minor breaking change to the language. This means that there might be observable changes or valid Rust 2018 code that fails to compile once you move to Rust Edition 2021.
39
+
40
+
When running `cargo fix --edition`, Cargo will update the closures in your code to help you migrate to Rust 2021, as described below in [Migrations](#migrations).
39
41
### Wild Card Patterns
40
42
Closures now only capture data that needs to be read, which means the following closures will not capture `x`
41
43
@@ -46,7 +48,7 @@ let c = || {
46
48
};
47
49
48
50
let c = || match x {
49
-
_ => prinln!("Hello World!")
51
+
_ => println!("Hello World!")
50
52
};
51
53
```
52
54
@@ -68,11 +70,11 @@ Since only a part of a variable might be captured instead of the entire variable
68
70
69
71
70
72
### Auto Traits
71
-
Structs or tuples that implement (an) auto trait(s) and are passed along in a closure may no longer guarantee that the closure can also implement that/those auto trait(s).
73
+
Structs or tuples that implement auto traits and are passed along in a closure may no longer guarantee that the closure can also implement those auto traits.
72
74
73
75
For instance, a common way to allow passing around raw pointers between threads is to wrap them in a struct and then implement `Send`/`Sync` auto trait for the wrapper. The closure that is passed to `thread::spawn` uses the specific fields within the wrapper but the entire wrapper is captured regardless. Since the wrapper is `Send`/`Sync`, the code is considered safe and therefore compiles successfully.
74
76
75
-
With this feature only the specific field mentioned in the closure gets captured, which wasn't originally `Send`/`Sync` defeating the purpose of the wrapper.
77
+
With disjoint captures, only the specific field mentioned in the closure gets captured, which wasn't originally `Send`/`Sync` defeating the purpose of the wrapper.
76
78
77
79
78
80
```rust,ignore
@@ -90,10 +92,12 @@ let c = thread::spawn(move || {
90
92
91
93
## Migrations
92
94
93
-
This new behavior is only activated in the new edition, or by specifically enabling it using `#[feature(capture_disjoint_fields)]`,
95
+
This new behavior is only activated starting in the 2021 edition,
94
96
since it can change the order in which fields are dropped and can impact auto trait usage with closures.
95
97
96
-
As for all edition changes, an automatic migration is available.
97
-
If you would like to be warned of semantics change that may impact your code, you can [use the lint](https://doc.rust-lang.org/rustc/lints/levels.html)`disjoint_capture_migrations`. The lint is also supported with [cargo fix](https://doc.rust-lang.org/cargo/commands/cargo-fix.html)to automatically migrate your code.
98
+
When running `cargo fix --edition`, the closures in your code may be updated so that they will retain the old behavior on both the 2018 and 2021 editions.
99
+
It does this by enabling the `disjoint_capture_migration` lint which adds statements like `let _ = &a;` inside the closure to force the entire variable to be captured as before.
98
100
99
-
The migration fix involves adding `let _ = &a;` inside the closure to force the entire variable to be captured as before.
101
+
After migrating, it is recommended to inspect the changes and see if they are necessary.
102
+
After changing the edition to 2021, you can try to remove the new statements and test that the closure works as expected.
103
+
You should review these closures, and ensure that the changes described above will not cause any problems.
0 commit comments