diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index cf3483d4c00..df32fbd4b33 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -14,8 +14,8 @@ use rustc_middle::hir::nested_filter; use rustc_middle::traits::Reveal; use rustc_middle::ty::{ - self, Binder, BoundConstness, Clause, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, TraitPredicate, - Ty, TyCtxt, + self, Binder, BoundConstness, Clause, GenericArgKind, GenericParamDefKind, ImplPolarity, ParamEnv, PredicateKind, + TraitPredicate, Ty, TyCtxt, }; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; @@ -366,6 +366,15 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h if ty_subs.types().any(|ty| !implements_trait(cx, ty, clone_id, &[])) { return; } + // `#[repr(packed)]` structs with type/const parameters can't derive `Clone`. + // https://github.com/rust-lang/rust-clippy/issues/10188 + if ty_adt.repr().packed() + && ty_subs + .iter() + .any(|arg| matches!(arg.unpack(), GenericArgKind::Type(_) | GenericArgKind::Const(_))) + { + return; + } span_lint_and_note( cx, diff --git a/tests/ui/derive.rs b/tests/ui/derive.rs index c629c0e5353..843e1df8bc6 100644 --- a/tests/ui/derive.rs +++ b/tests/ui/derive.rs @@ -85,4 +85,15 @@ fn clone(&self) -> Self { } } +// https://github.com/rust-lang/rust-clippy/issues/10188 +#[repr(packed)] +#[derive(Copy)] +struct Packed(T); + +impl Clone for Packed { + fn clone(&self) -> Self { + *self + } +} + fn main() {}