<commit_before>use rustc::lint::*;
use rustc::ty::subst::Subst;
use rustc::ty::TypeVariants;
use rustc::ty;
use rustc::hir::*;
use syntax::ast::{Attribute, MetaItemKind};
use syntax::codemap::Span;
use utils::paths;
use utils::{match_path, span_lint_and_then};

/// **What it does:** This lint warns about deriving `Hash` but implementing `PartialEq`
/// explicitly.
///
/// **Why is this bad?** The implementation of these traits must agree (for example for use with
/// `HashMap`) so it’s probably a bad idea to use a default-generated `Hash` implementation  with
/// an explicitly defined `PartialEq`. In particular, the following must hold for any type:
///
/// ```rust
/// k1 == k2 ⇒ hash(k1) == hash(k2)
/// ```
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// #[derive(Hash)]
/// struct Foo;
///
/// impl PartialEq for Foo {
///     ..
/// }
/// ```
declare_lint! {
    pub DERIVE_HASH_XOR_EQ,
    Warn,
    "deriving `Hash` but implementing `PartialEq` explicitly"
}

/// **What it does:** This lint warns about explicit `Clone` implementation for `Copy` types.
///
/// **Why is this bad?** To avoid surprising behaviour, these traits should agree and the behaviour
/// of `Copy` cannot be overridden. In almost all situations a `Copy` type should have a `Clone`
/// implementation that does nothing more than copy the object, which is what
/// `#[derive(Copy, Clone)]` gets you.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// #[derive(Copy)]
/// struct Foo;
///
/// impl Clone for Foo {
///     ..
/// }
/// ```
declare_lint! {
    pub EXPL_IMPL_CLONE_ON_COPY,
    Warn,
    "implementing `Clone` explicitly on `Copy` types"
}

pub struct Derive;

impl LintPass for Derive {
    fn get_lints(&self) -> LintArray {
        lint_array!(EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ)
    }
}

impl LateLintPass for Derive {
    fn check_item(&mut self, cx: &LateContext, item: &Item) {
        if_let_chain! {[
            let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node
        ], {
            let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty;
            let is_automatically_derived = item.attrs.iter().any(is_automatically_derived);

            check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);

            if !is_automatically_derived {
                check_copy_clone(cx, item, trait_ref, ty);
            }
        }}
    }
}

/// Implementation of the `DERIVE_HASH_XOR_EQ` lint.
fn check_hash_peq<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>, hash_is_automatically_derived: bool) {
    if_let_chain! {[
        match_path(&trait_ref.path, &paths::HASH),
        let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait()
    ], {
        let peq_trait_def = cx.tcx.lookup_trait_def(peq_trait_def_id);

        // Look for the PartialEq implementations for `ty`
        peq_trait_def.for_each_relevant_impl(cx.tcx, ty, |impl_id| {
            let peq_is_automatically_derived = cx.tcx.get_attrs(impl_id).iter().any(is_automatically_derived);<commit_msg>Remove useless `if_let_chain`<commit_after>use rustc::lint::*;
use rustc::ty::subst::Subst;
use rustc::ty::TypeVariants;
use rustc::ty;
use rustc::hir::*;
use syntax::ast::{Attribute, MetaItemKind};
use syntax::codemap::Span;
use utils::paths;
use utils::{match_path, span_lint_and_then};

/// **What it does:** This lint warns about deriving `Hash` but implementing `PartialEq`
/// explicitly.
///
/// **Why is this bad?** The implementation of these traits must agree (for example for use with
/// `HashMap`) so it’s probably a bad idea to use a default-generated `Hash` implementation  with
/// an explicitly defined `PartialEq`. In particular, the following must hold for any type:
///
/// ```rust
/// k1 == k2 ⇒ hash(k1) == hash(k2)
/// ```
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// #[derive(Hash)]
/// struct Foo;
///
/// impl PartialEq for Foo {
///     ..
/// }
/// ```
declare_lint! {
    pub DERIVE_HASH_XOR_EQ,
    Warn,
    "deriving `Hash` but implementing `PartialEq` explicitly"
}

/// **What it does:** This lint warns about explicit `Clone` implementation for `Copy` types.
///
/// **Why is this bad?** To avoid surprising behaviour, these traits should agree and the behaviour
/// of `Copy` cannot be overridden. In almost all situations a `Copy` type should have a `Clone`
/// implementation that does nothing more than copy the object, which is what
/// `#[derive(Copy, Clone)]` gets you.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// #[derive(Copy)]
/// struct Foo;
///
/// impl Clone for Foo {
///     ..
/// }
/// ```
declare_lint! {
    pub EXPL_IMPL_CLONE_ON_COPY,
    Warn,
    "implementing `Clone` explicitly on `Copy` types"
}

pub struct Derive;

impl LintPass for Derive {
    fn get_lints(&self) -> LintArray {
        lint_array!(EXPL_IMPL_CLONE_ON_COPY, DERIVE_HASH_XOR_EQ)
    }
}

impl LateLintPass for Derive {
    fn check_item(&mut self, cx: &LateContext, item: &Item) {
        if let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
            let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty;
            let is_automatically_derived = item.attrs.iter().any(is_automatically_derived);

            check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);

            if !is_automatically_derived {
                check_copy_clone(cx, item, trait_ref, ty);
            }
        }
    }
}

/// Implementation of the `DERIVE_HASH_XOR_EQ` lint.
fn check_hash_peq<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>, hash_is_automatically_derived: bool) {
    if_let_chain! {[
        match_path(&trait_ref.path, &paths::HASH),
        let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait()
    ], {
        let peq_trait_def = cx.tcx.lookup_trait_def(peq_trait_def_id);

        // Look for the PartialEq implementations for `ty`
        peq_trait_def.for_each_relevant_impl(cx.tcx, ty, |impl_id| {
            let peq_is_automatically_derived = cx.tcx.get_attrs(impl_id).iter().any(is_automatically_derived);
{'fraction_non_alphanumeric': 0.1600128783000644, 'fraction_numerical': 0.00128783000643915, 'mean_word_length': 3.1392405063291138, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3680722', 'n_tokens_mistral': 2123, 'n_tokens_neox': 2140, 'n_words': 549}