Rollup merge of #131153 - VulnBandit:copy_impl_vuln, r=compiler-errors
Improve duplicate derive Copy/Clone diagnostics
Improve duplicate derive Copy/Clone diagnostics.
Closes #131083
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 3871816..15cc9c2 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -10,6 +10,7 @@
use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
+use rustc_trait_selection::infer::InferCtxtExt;
use tracing::debug;
use crate::MirBorrowckCtxt;
@@ -267,6 +268,15 @@
kind,
self.is_upvar_field_projection(original_path.as_ref())
);
+ if self.has_ambiguous_copy(original_path.ty(self.body, self.infcx.tcx).ty) {
+ // If the type may implement Copy, skip the error.
+ // It's an error with the Copy implementation (e.g. duplicate Copy) rather than borrow check
+ self.dcx().span_delayed_bug(
+ span,
+ "Type may implement copy, but there is no other error.",
+ );
+ return;
+ }
(
match kind {
&IllegalMoveOriginKind::BorrowedContent { target_place } => self
@@ -291,6 +301,13 @@
self.buffer_error(err);
}
+ fn has_ambiguous_copy(&mut self, ty: Ty<'tcx>) -> bool {
+ let Some(copy_trait_def) = self.infcx.tcx.lang_items().copy_trait() else { return false };
+ // This is only going to be ambiguous if there are incoherent impls, because otherwise
+ // ambiguity should never happen in MIR.
+ self.infcx.type_implements_trait(copy_trait_def, [ty], self.param_env).may_apply()
+ }
+
fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'infcx> {
let description = if place.projection.len() == 1 {
format!("static item {}", self.describe_any_place(place.as_ref()))
diff --git a/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.rs b/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.rs
new file mode 100644
index 0000000..c4fb620
--- /dev/null
+++ b/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.rs
@@ -0,0 +1,11 @@
+// Duplicate implementations of Copy/Clone should not trigger
+// borrow check warnings
+// See #131083
+
+#[derive(Copy, Clone)]
+#[derive(Copy, Clone)]
+//~^ ERROR conflicting implementations of trait `Clone` for type `E`
+//~| ERROR conflicting implementations of trait `Copy` for type `E`
+enum E {}
+
+fn main() {}
diff --git a/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr b/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr
new file mode 100644
index 0000000..f8e1db3
--- /dev/null
+++ b/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr
@@ -0,0 +1,23 @@
+error[E0119]: conflicting implementations of trait `Copy` for type `E`
+ --> $DIR/duplicate-derive-copy-clone-diagnostics.rs:6:10
+ |
+LL | #[derive(Copy, Clone)]
+ | ---- first implementation here
+LL | #[derive(Copy, Clone)]
+ | ^^^^ conflicting implementation for `E`
+ |
+ = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0119]: conflicting implementations of trait `Clone` for type `E`
+ --> $DIR/duplicate-derive-copy-clone-diagnostics.rs:6:16
+ |
+LL | #[derive(Copy, Clone)]
+ | ----- first implementation here
+LL | #[derive(Copy, Clone)]
+ | ^^^^^ conflicting implementation for `E`
+ |
+ = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0119`.