Skip to content

Commit

Permalink
Improve duplicate derive Copy/Clone diagnostics
Browse files Browse the repository at this point in the history
  • Loading branch information
VulnBandit committed Oct 3, 2024
1 parent 360f7d7 commit ae2568a
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
17 changes: 17 additions & 0 deletions compiler/rustc_borrowck/src/diagnostics/move_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use rustc_middle::ty::{self, Ty};
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;
Expand Down Expand Up @@ -267,6 +268,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
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.span_delayed_bug(
span,
"Type may implement copy, but there is no other error.",
);
return;
}
(
match kind {
&IllegalMoveOriginKind::BorrowedContent { target_place } => self
Expand All @@ -291,6 +301,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
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()))
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/derives/duplicate-derive-copy-clone-diagnostics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Duplicate implementations of Copy/Clone should not trigger
// borrow check warnings
// See #131083

#[derive(Copy, Clone)]
#[derive(Copy, Clone)]
//~^ ERROR conflicting implementations of trait `Copy`
enum E {}

fn main() {}
23 changes: 23 additions & 0 deletions tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
error[E0119]: conflicting implementations of trait `Copy` for type `E`
--> $DIR/duplicate-derive-copy-clone-diagnostics.rs:2: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:2: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`.

0 comments on commit ae2568a

Please sign in to comment.