From 01b810e0523806445273e6aaeb26d1c77c66556c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 13 Mar 2024 05:46:53 +0000 Subject: [PATCH] Silence redundant clone suggestion --- .../src/diagnostics/conflict_errors.rs | 5 +++++ tests/ui/moves/needs-clone-through-deref.fixed | 18 ++++++++++++++++++ tests/ui/moves/needs-clone-through-deref.rs | 1 + .../ui/moves/needs-clone-through-deref.stderr | 6 +----- 4 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 tests/ui/moves/needs-clone-through-deref.fixed diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 4bbeadbae70..3bc9f39d0f8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1027,6 +1027,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { span: Span, ) { let tcx = self.infcx.tcx; + if let Some(_) = self.clone_on_reference(expr) { + // Avoid redundant clone suggestion already suggested in `explain_captures`. + // See `tests/ui/moves/needs-clone-through-deref.rs` + return; + } // Try to find predicates on *generic params* that would allow copying `ty` let suggestion = if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { diff --git a/tests/ui/moves/needs-clone-through-deref.fixed b/tests/ui/moves/needs-clone-through-deref.fixed new file mode 100644 index 00000000000..8b201c4720d --- /dev/null +++ b/tests/ui/moves/needs-clone-through-deref.fixed @@ -0,0 +1,18 @@ +//@ run-rustfix +#![allow(dead_code, noop_method_call)] +use std::ops::Deref; +struct S(Vec); +impl Deref for S { + type Target = Vec; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl S { + fn foo(&self) { + // `self.clone()` returns `&S`, not `Vec` + for _ in as Clone>::clone(&self).into_iter() {} //~ ERROR cannot move out of dereference of `S` + } +} +fn main() {} diff --git a/tests/ui/moves/needs-clone-through-deref.rs b/tests/ui/moves/needs-clone-through-deref.rs index 245b7c167fa..ca57478ba98 100644 --- a/tests/ui/moves/needs-clone-through-deref.rs +++ b/tests/ui/moves/needs-clone-through-deref.rs @@ -1,3 +1,4 @@ +//@ run-rustfix #![allow(dead_code, noop_method_call)] use std::ops::Deref; struct S(Vec); diff --git a/tests/ui/moves/needs-clone-through-deref.stderr b/tests/ui/moves/needs-clone-through-deref.stderr index 8357ed9ff79..1f9aefeb4dd 100644 --- a/tests/ui/moves/needs-clone-through-deref.stderr +++ b/tests/ui/moves/needs-clone-through-deref.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of dereference of `S` - --> $DIR/needs-clone-through-deref.rs:14:18 + --> $DIR/needs-clone-through-deref.rs:15:18 | LL | for _ in self.clone().into_iter() {} | ^^^^^^^^^^^^ ----------- value moved due to this method call @@ -12,10 +12,6 @@ help: you can `clone` the value and consume it, but this might not be your desir | LL | for _ in as Clone>::clone(&self).into_iter() {} | ++++++++++++++++++++++++++++++ ~ -help: consider cloning the value if the performance cost is acceptable - | -LL | for _ in self.clone().clone().into_iter() {} - | ++++++++ error: aborting due to 1 previous error