Point at destructor when denying deriving Copy

This commit is contained in:
Esteban Küber 2026-01-18 21:28:58 +00:00
parent dd8148373f
commit 20000ca25a
6 changed files with 27 additions and 5 deletions

View file

@ -142,6 +142,7 @@ hir_analysis_copy_impl_on_non_adt =
hir_analysis_copy_impl_on_type_with_dtor =
the trait `Copy` cannot be implemented for this type; the type has a destructor
.label = `Copy` not allowed on types with destructors
.note = destructor declared here
hir_analysis_cross_crate_traits = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type, not `{$self_ty}`
.label = can't implement cross-crate trait with a default impl for non-struct/enum type

View file

@ -121,9 +121,10 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
Err(tcx.dcx().emit_err(errors::CopyImplOnNonAdt { span }))
}
Err(CopyImplementationError::HasDestructor) => {
Err(CopyImplementationError::HasDestructor(did)) => {
let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span }))
let impl_ = tcx.def_span(did);
Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span, impl_ }))
}
Err(CopyImplementationError::HasUnsafeFields) => {
let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;

View file

@ -278,6 +278,8 @@ pub(crate) struct CopyImplOnTypeWithDtor {
#[primary_span]
#[label]
pub span: Span,
#[note]
pub impl_: Span,
}
#[derive(Diagnostic)]

View file

@ -13,7 +13,7 @@ use crate::traits::{self, FulfillmentError, Obligation, ObligationCause};
pub enum CopyImplementationError<'tcx> {
InfringingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
NotAnAdt,
HasDestructor,
HasDestructor(hir::def_id::DefId),
HasUnsafeFields,
}
@ -76,8 +76,8 @@ pub fn type_allowed_to_implement_copy<'tcx>(
)
.map_err(CopyImplementationError::InfringingFields)?;
if adt.has_dtor(tcx) {
return Err(CopyImplementationError::HasDestructor);
if let Some(did) = adt.destructor(tcx).map(|dtor| dtor.did) {
return Err(CopyImplementationError::HasDestructor(did));
}
if impl_safety.is_safe() && self_type.has_unsafe_fields() {

View file

@ -5,6 +5,12 @@ LL | #[derive(Copy, Clone)]
| ---- in this derive macro expansion
LL | struct Foo;
| ^^^ `Copy` not allowed on types with destructors
|
note: destructor declared here
--> $DIR/copy-drop-mutually-exclusive.rs:7:5
|
LL | fn drop(&mut self) {}
| ^^^^^^^^^^^^^^^^^^
error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor
--> $DIR/copy-drop-mutually-exclusive.rs:11:8
@ -13,6 +19,12 @@ LL | #[derive(Copy, Clone)]
| ---- in this derive macro expansion
LL | struct Bar<T>(::std::marker::PhantomData<T>);
| ^^^ `Copy` not allowed on types with destructors
|
note: destructor declared here
--> $DIR/copy-drop-mutually-exclusive.rs:14:5
|
LL | fn drop(&mut self) {}
| ^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors

View file

@ -5,6 +5,12 @@ LL | #[derive(Copy)]
| ---- in this derive macro expansion
LL | struct Foo;
| ^^^ `Copy` not allowed on types with destructors
|
note: destructor declared here
--> $DIR/E0184.rs:5:5
|
LL | fn drop(&mut self) {
| ^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error