diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 92ca868eb9925..447bf7d091a72 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -303,10 +303,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } 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.infcx.param_env).may_apply() + let Some(copy_def_id) = self.infcx.tcx.lang_items().copy_trait() else { return false }; + + // Avoid bogus move errors because of an incoherent `Copy` impl. + self.infcx.type_implements_trait(copy_def_id, [ty], self.infcx.param_env).may_apply() + && self.infcx.tcx.coherent_trait(copy_def_id).is_err() } fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'infcx> { diff --git a/tests/ui/borrowck/copy-overflow.rs b/tests/ui/borrowck/copy-overflow.rs new file mode 100644 index 0000000000000..5aa1afdee68e5 --- /dev/null +++ b/tests/ui/borrowck/copy-overflow.rs @@ -0,0 +1,16 @@ +// Regression test for . + +// We were previously suppressing the copy error in the `Clone` impl because we assumed +// that the only way we get `Copy` ambiguity errors was due to incoherent impls. This is +// not true, since ambiguities can be encountered due to overflows (among other ways). + +struct S(Option<&'static T>); + +impl Copy for S where S: Copy + Clone {} +impl Clone for S { + fn clone(&self) -> Self { + *self + //~^ ERROR cannot move out of `*self` which is behind a shared reference + } +} +fn main() {} diff --git a/tests/ui/borrowck/copy-overflow.stderr b/tests/ui/borrowck/copy-overflow.stderr new file mode 100644 index 0000000000000..3f601276f8fdd --- /dev/null +++ b/tests/ui/borrowck/copy-overflow.stderr @@ -0,0 +1,15 @@ +error[E0507]: cannot move out of `*self` which is behind a shared reference + --> $DIR/copy-overflow.rs:12:9 + | +LL | *self + | ^^^^^ move occurs because `*self` has type `S`, which does not implement the `Copy` trait + | +help: consider cloning the value if the performance cost is acceptable + | +LL - *self +LL + self.clone() + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0507`.