Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 36eb544

Browse files
committed
Add note clarifying why a closure no longer implements a trait
1 parent 2900c1a commit 36eb544

File tree

7 files changed

+46
-10
lines changed

7 files changed

+46
-10
lines changed

compiler/rustc_typeck/src/check/upvar.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
535535
captured_names,
536536
));
537537
}
538+
539+
if reasons.contains("closure trait implementation") {
540+
let closure_body_span = self.tcx.hir().span(body_id.hir_id);
541+
let closure_ending_span = self.tcx.sess.source_map().guess_head_span(closure_body_span).shrink_to_lo();
542+
543+
let missing_trait = &reasons[..reasons.find("closure trait implementation").unwrap() - 1];
544+
545+
diagnostics_builder.span_label(closure_ending_span, format!("in Rust 2018, this closure would implement {} as `{}` implements {}, but in Rust 2021, this closure will no longer implement {} as {} does not implement {}",
546+
missing_trait,
547+
self.tcx.hir().name(*var_hir_id),
548+
missing_trait,
549+
missing_trait,
550+
captured_names,
551+
missing_trait,
552+
));
553+
}
538554
}
539555
diagnostics_builder.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>");
540556
let closure_body_span = self.tcx.hir().span(body_id.hir_id);

src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ fn test_send_trait() {
1313
let fptr = SendPointer(&mut f as *mut i32);
1414
thread::spawn(move || { let _ = &fptr; unsafe {
1515
//~^ ERROR: `Send` closure trait implementation
16+
//~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
1617
//~| NOTE: for more information, see
1718
//~| HELP: add a dummy let to cause `fptr` to be fully captured
1819
*fptr.0 = 20;
@@ -32,6 +33,7 @@ fn test_sync_trait() {
3233
let fptr = SyncPointer(f);
3334
thread::spawn(move || { let _ = &fptr; unsafe {
3435
//~^ ERROR: `Sync`, `Send` closure trait implementation
36+
//~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
3537
//~| NOTE: for more information, see
3638
//~| HELP: add a dummy let to cause `fptr` to be fully captured
3739
*fptr.0.0 = 20;
@@ -55,6 +57,7 @@ fn test_clone_trait() {
5557
let f = U(S(String::from("Hello World")), T(0));
5658
let c = || { let _ = &f;
5759
//~^ ERROR: `Clone` closure trait implementation, and drop order
60+
//~| NOTE: in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
5861
//~| NOTE: for more information, see
5962
//~| HELP: add a dummy let to cause `f` to be fully captured
6063
let f_1 = f.1;

src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ fn test_send_trait() {
1313
let fptr = SendPointer(&mut f as *mut i32);
1414
thread::spawn(move || unsafe {
1515
//~^ ERROR: `Send` closure trait implementation
16+
//~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
1617
//~| NOTE: for more information, see
1718
//~| HELP: add a dummy let to cause `fptr` to be fully captured
1819
*fptr.0 = 20;
@@ -32,6 +33,7 @@ fn test_sync_trait() {
3233
let fptr = SyncPointer(f);
3334
thread::spawn(move || unsafe {
3435
//~^ ERROR: `Sync`, `Send` closure trait implementation
36+
//~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
3537
//~| NOTE: for more information, see
3638
//~| HELP: add a dummy let to cause `fptr` to be fully captured
3739
*fptr.0.0 = 20;
@@ -55,6 +57,7 @@ fn test_clone_trait() {
5557
let f = U(S(String::from("Hello World")), T(0));
5658
let c = || {
5759
//~^ ERROR: `Clone` closure trait implementation, and drop order
60+
//~| NOTE: in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
5861
//~| NOTE: for more information, see
5962
//~| HELP: add a dummy let to cause `f` to be fully captured
6063
let f_1 = f.1;

src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error: changes to closure capture in Rust 2021 will affect `Send` closure trait
22
--> $DIR/auto_traits.rs:14:19
33
|
44
LL | thread::spawn(move || unsafe {
5-
| ___________________^
5+
| ^ - in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
6+
| ___________________|
7+
| |
8+
LL | |
69
LL | |
710
LL | |
811
LL | |
@@ -24,15 +27,18 @@ LL | thread::spawn(move || { let _ = &fptr; unsafe {
2427
LL |
2528
LL |
2629
LL |
27-
LL | *fptr.0 = 20;
2830
LL |
31+
LL | *fptr.0 = 20;
2932
...
3033

3134
error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` closure trait implementation
32-
--> $DIR/auto_traits.rs:33:19
35+
--> $DIR/auto_traits.rs:34:19
3336
|
3437
LL | thread::spawn(move || unsafe {
35-
| ___________________^
38+
| ^ - in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
39+
| ___________________|
40+
| |
41+
LL | |
3642
LL | |
3743
LL | |
3844
LL | |
@@ -49,15 +55,18 @@ LL | thread::spawn(move || { let _ = &fptr; unsafe {
4955
LL |
5056
LL |
5157
LL |
52-
LL | *fptr.0.0 = 20;
5358
LL |
59+
LL | *fptr.0.0 = 20;
5460
...
5561

5662
error: changes to closure capture in Rust 2021 will affect `Clone` closure trait implementation, and drop order
57-
--> $DIR/auto_traits.rs:56:13
63+
--> $DIR/auto_traits.rs:58:13
5864
|
5965
LL | let c = || {
60-
| _____________^
66+
| ^ - in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
67+
| _____________|
68+
| |
69+
LL | |
6170
LL | |
6271
LL | |
6372
LL | |
@@ -78,8 +87,8 @@ LL | let c = || { let _ = &f;
7887
LL |
7988
LL |
8089
LL |
81-
LL | let f_1 = f.1;
8290
LL |
91+
LL | let f_1 = f.1;
8392
...
8493

8594
error: aborting due to 3 previous errors

src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ where
1919
let f = panic::AssertUnwindSafe(f);
2020
let result = panic::catch_unwind(move || { let _ = &f;
2121
//~^ ERROR: `UnwindSafe`, `RefUnwindSafe` closure trait implementation
22+
//~| NOTE: in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
2223
//~| NOTE: for more information, see
2324
//~| HELP: add a dummy let to cause `f` to be fully captured
2425
f.0()

src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ where
1919
let f = panic::AssertUnwindSafe(f);
2020
let result = panic::catch_unwind(move || {
2121
//~^ ERROR: `UnwindSafe`, `RefUnwindSafe` closure trait implementation
22+
//~| NOTE: in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
2223
//~| NOTE: for more information, see
2324
//~| HELP: add a dummy let to cause `f` to be fully captured
2425
f.0()

src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error: changes to closure capture in Rust 2021 will affect `UnwindSafe`, `RefUnw
22
--> $DIR/mir_calls_to_shims.rs:20:38
33
|
44
LL | let result = panic::catch_unwind(move || {
5-
| ______________________________________^
5+
| ^ - in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
6+
| ______________________________________|
7+
| |
8+
LL | |
69
LL | |
710
LL | |
811
LL | |
@@ -24,8 +27,8 @@ LL | let result = panic::catch_unwind(move || { let _ = &f;
2427
LL |
2528
LL |
2629
LL |
27-
LL | f.0()
2830
LL |
31+
LL | f.0()
2932
...
3033

3134
error: aborting due to previous error

0 commit comments

Comments
 (0)