diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index a5c4e161771a..9806fd95c8f5 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -535,6 +535,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { captured_names, )); } + + if reasons.contains("closure trait implementation") { + let closure_body_span = self.tcx.hir().span(body_id.hir_id); + let closure_ending_span = self.tcx.sess.source_map().guess_head_span(closure_body_span).shrink_to_lo(); + + let missing_trait = &reasons[..reasons.find("closure trait implementation").unwrap() - 1]; + + 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 {}", + missing_trait, + self.tcx.hir().name(*var_hir_id), + missing_trait, + missing_trait, + captured_names, + missing_trait, + )); + } } diagnostics_builder.note("for more information, see "); let closure_body_span = self.tcx.hir().span(body_id.hir_id); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed index ca55152cc2a8..4cc8a2b54be8 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed @@ -13,6 +13,7 @@ fn test_send_trait() { let fptr = SendPointer(&mut f as *mut i32); thread::spawn(move || { let _ = &fptr; unsafe { //~^ ERROR: `Send` closure trait implementation + //~| 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` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0 = 20; @@ -32,6 +33,7 @@ fn test_sync_trait() { let fptr = SyncPointer(f); thread::spawn(move || { let _ = &fptr; unsafe { //~^ ERROR: `Sync`, `Send` closure trait implementation + //~| 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` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0.0 = 20; @@ -55,6 +57,7 @@ fn test_clone_trait() { let f = U(S(String::from("Hello World")), T(0)); let c = || { let _ = &f; //~^ ERROR: `Clone` closure trait implementation, and drop order + //~| 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` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured let f_1 = f.1; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs index 66c43cd865be..a75c0aa52798 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs @@ -13,6 +13,7 @@ fn test_send_trait() { let fptr = SendPointer(&mut f as *mut i32); thread::spawn(move || unsafe { //~^ ERROR: `Send` closure trait implementation + //~| 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` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0 = 20; @@ -32,6 +33,7 @@ fn test_sync_trait() { let fptr = SyncPointer(f); thread::spawn(move || unsafe { //~^ ERROR: `Sync`, `Send` closure trait implementation + //~| 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` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0.0 = 20; @@ -55,6 +57,7 @@ fn test_clone_trait() { let f = U(S(String::from("Hello World")), T(0)); let c = || { //~^ ERROR: `Clone` closure trait implementation, and drop order + //~| 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` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured let f_1 = f.1; diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr index 38f8976058d3..c8867e1ac92a 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr @@ -2,7 +2,10 @@ error: changes to closure capture in Rust 2021 will affect `Send` closure trait --> $DIR/auto_traits.rs:14:19 | LL | thread::spawn(move || unsafe { - | ___________________^ + | ^ - 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` + | ___________________| + | | +LL | | LL | | LL | | LL | | @@ -24,15 +27,18 @@ LL | thread::spawn(move || { let _ = &fptr; unsafe { LL | LL | LL | -LL | *fptr.0 = 20; LL | +LL | *fptr.0 = 20; ... error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` closure trait implementation - --> $DIR/auto_traits.rs:33:19 + --> $DIR/auto_traits.rs:34:19 | LL | thread::spawn(move || unsafe { - | ___________________^ + | ^ - 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` + | ___________________| + | | +LL | | LL | | LL | | LL | | @@ -49,15 +55,18 @@ LL | thread::spawn(move || { let _ = &fptr; unsafe { LL | LL | LL | -LL | *fptr.0.0 = 20; LL | +LL | *fptr.0.0 = 20; ... error: changes to closure capture in Rust 2021 will affect `Clone` closure trait implementation, and drop order - --> $DIR/auto_traits.rs:56:13 + --> $DIR/auto_traits.rs:58:13 | LL | let c = || { - | _____________^ + | ^ - 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` + | _____________| + | | +LL | | LL | | LL | | LL | | @@ -78,8 +87,8 @@ LL | let c = || { let _ = &f; LL | LL | LL | -LL | let f_1 = f.1; LL | +LL | let f_1 = f.1; ... error: aborting due to 3 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed index cb3148214b4b..f6e4f159ad08 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed @@ -19,6 +19,7 @@ where let f = panic::AssertUnwindSafe(f); let result = panic::catch_unwind(move || { let _ = &f; //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` closure trait implementation + //~| 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` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured f.0() diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs index f6f8ad2c5207..f6481d51fcd3 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs @@ -19,6 +19,7 @@ where let f = panic::AssertUnwindSafe(f); let result = panic::catch_unwind(move || { //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` closure trait implementation + //~| 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` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured f.0() diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr index 9a45e276fcdf..bc8580b23b2d 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr @@ -2,7 +2,10 @@ error: changes to closure capture in Rust 2021 will affect `UnwindSafe`, `RefUnw --> $DIR/mir_calls_to_shims.rs:20:38 | LL | let result = panic::catch_unwind(move || { - | ______________________________________^ + | ^ - 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` + | ______________________________________| + | | +LL | | LL | | LL | | LL | | @@ -24,8 +27,8 @@ LL | let result = panic::catch_unwind(move || { let _ = &f; LL | LL | LL | -LL | f.0() LL | +LL | f.0() ... error: aborting due to previous error