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;
/// }
/// ```
#[clippy::version = "pre 1.29.0"]
- pub DERIVE_HASH_XOR_EQ,
+ pub DERIVED_HASH_WITH_MANUAL_EQ,
correctness,
"deriving `Hash` but implementing `PartialEq` explicitly"
}
declare_lint_pass!(Derive => [
EXPL_IMPL_CLONE_ON_COPY,
- DERIVE_HASH_XOR_EQ,
+ DERIVED_HASH_WITH_MANUAL_EQ,
DERIVE_ORD_XOR_PARTIAL_ORD,
UNSAFE_DERIVE_DESERIALIZE,
DERIVE_PARTIAL_EQ_WITHOUT_EQ
}
}
-/// Implementation of the `DERIVE_HASH_XOR_EQ` lint.
+/// Implementation of the `DERIVED_HASH_WITH_MANUAL_EQ` lint.
fn check_hash_peq<'tcx>(
cx: &LateContext<'tcx>,
span: Span,
cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| {
let peq_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived);
- if peq_is_automatically_derived == hash_is_automatically_derived {
+ if !hash_is_automatically_derived || peq_is_automatically_derived {
return;
}
// Only care about `impl PartialEq<Foo> for Foo`
// For `impl PartialEq<B> for A, input_types is [A, B]
- if trait_ref.substs.type_at(1) == ty {
- let mess = if peq_is_automatically_derived {
- "you are implementing `Hash` explicitly but have derived `PartialEq`"
- } else {
- "you are deriving `Hash` but have implemented `PartialEq` explicitly"
- };
-
+ if trait_ref.subst_identity().substs.type_at(1) == ty {
span_lint_and_then(
cx,
- DERIVE_HASH_XOR_EQ,
+ DERIVED_HASH_WITH_MANUAL_EQ,
span,
- mess,
+ "you are deriving `Hash` but have implemented `PartialEq` explicitly",
|diag| {
if let Some(local_def_id) = impl_id.as_local() {
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
// Only care about `impl PartialOrd<Foo> for Foo`
// For `impl PartialOrd<B> for A, input_types is [A, B]
- if trait_ref.substs.type_at(1) == ty {
+ if trait_ref.subst_identity().substs.type_at(1) == ty {
let mess = if partial_ord_is_automatically_derived {
"you are implementing `Ord` explicitly but have derived `PartialOrd`"
} else {
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,