diff options
| author | Michael Goulet <michael@errs.io> | 2025-07-21 16:07:12 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2025-07-21 16:07:29 +0000 |
| commit | b5d36e5294d3354ad8feec86b27c698e368c88a6 (patch) | |
| tree | 786113548170ad50aa1c01f4156a767123d6eb37 | |
| parent | 67819923ac8ea353aaa775303f4c3aacbf41d010 (diff) | |
| download | rust-b5d36e5294d3354ad8feec86b27c698e368c88a6.tar.gz rust-b5d36e5294d3354ad8feec86b27c698e368c88a6.zip | |
Dont ICE on copy error being suppressed due to overflow
| -rw-r--r-- | compiler/rustc_borrowck/src/diagnostics/move_errors.rs | 9 | ||||
| -rw-r--r-- | tests/ui/borrowck/copy-overflow.rs | 16 | ||||
| -rw-r--r-- | tests/ui/borrowck/copy-overflow.stderr | 15 |
3 files changed, 36 insertions, 4 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 92ca868eb99..447bf7d091a 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 00000000000..5aa1afdee68 --- /dev/null +++ b/tests/ui/borrowck/copy-overflow.rs @@ -0,0 +1,16 @@ +// Regression test for <https://github.com/rust-lang/rust/issues/144165>. + +// 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<T: 'static>(Option<&'static T>); + +impl<T: 'static> Copy for S<T> where S<T>: Copy + Clone {} +impl<T: 'static> Clone for S<T> { + 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 00000000000..3f601276f8f --- /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<T>`, 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`. |
