From 0c7f8b0f89e3b4a8ed46074e39a4de160d098489 Mon Sep 17 00:00:00 2001 From: Daniel Sedlak Date: Sat, 16 Mar 2024 11:50:02 +0100 Subject: [PATCH] Fix diagnostics for async block cloning --- .../src/diagnostics/conflict_errors.rs | 10 +++++++++ .../borrowck/cloning-in-async-block-121547.rs | 11 ++++++++++ .../cloning-in-async-block-121547.stderr | 22 +++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 tests/ui/borrowck/cloning-in-async-block-121547.rs create mode 100644 tests/ui/borrowck/cloning-in-async-block-121547.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 35bd7d3799216..106e68a779cdb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -4,6 +4,7 @@ #![allow(rustc::untranslatable_diagnostic)] use either::Either; +use hir::ClosureKind; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan}; @@ -463,6 +464,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } = move_spans { // We already suggest cloning for these cases in `explain_captures`. + } else if let UseSpans::ClosureUse { + closure_kind: + ClosureKind::Coroutine(CoroutineKind::Desugared(_, CoroutineSource::Block)), + args_span: _, + capture_kind_span: _, + path_span, + } = move_spans + { + self.suggest_cloning(err, ty, expr, path_span); } else if self.suggest_hoisting_call_outside_loop(err, expr) { // The place where the the type moves would be misleading to suggest clone. // #121466 diff --git a/tests/ui/borrowck/cloning-in-async-block-121547.rs b/tests/ui/borrowck/cloning-in-async-block-121547.rs new file mode 100644 index 0000000000000..b2d8dbae977e4 --- /dev/null +++ b/tests/ui/borrowck/cloning-in-async-block-121547.rs @@ -0,0 +1,11 @@ +//@ edition:2021 + +async fn clone_async_block(value: String) { + for _ in 0..10 { + async { //~ ERROR: use of moved value: `value` [E0382] + drop(value); + //~^ HELP: consider cloning the value if the performance cost is acceptable + }.await + } +} +fn main() {} diff --git a/tests/ui/borrowck/cloning-in-async-block-121547.stderr b/tests/ui/borrowck/cloning-in-async-block-121547.stderr new file mode 100644 index 0000000000000..ae57e0018f8ab --- /dev/null +++ b/tests/ui/borrowck/cloning-in-async-block-121547.stderr @@ -0,0 +1,22 @@ +error[E0382]: use of moved value: `value` + --> $DIR/cloning-in-async-block-121547.rs:5:9 + | +LL | async fn clone_async_block(value: String) { + | ----- move occurs because `value` has type `String`, which does not implement the `Copy` trait +LL | for _ in 0..10 { + | -------------- inside of this loop +LL | / async { +LL | | drop(value); + | | ----- use occurs due to use in coroutine +LL | | +LL | | }.await + | |_________^ value moved here, in previous iteration of loop + | +help: consider cloning the value if the performance cost is acceptable + | +LL | drop(value.clone()); + | ++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`.