fn check_dupe_on_copy()

in gazebo_lint/src/lib.rs [368:400]


fn check_dupe_on_copy(cx: &LateContext, expr: &Expr) {
    if let ExprKind::MethodCall(method_call, method_span, args, _) = expr.kind {
        if args.len() == 1 && method_call.ident.name == sym!(dupe) {
            if let Some(dupe_trait) = clippy::get_trait_def_id(cx, &["gazebo", "dupe", "Dupe"]) {
                if let Some(copy_marker) = clippy::get_trait_def_id(cx, &["std", "marker", "Copy"])
                {
                    let mut duped_type = cx.typeck_results().expr_ty(&args[0]).peel_refs();
                    loop {
                        // Note that we could be calling `dupe` on a `&Foo`. All `&` types are
                        // `Copy`, so we actually need to make sure the current type we are looking
                        // at is `Dupe` as well so we correctly determine a `Foo` that is both
                        // `Dupe` and `Copy`, rather than a false positive because all `&`s are
                        // `Copy`.
                        if clippy::implements_trait(cx, duped_type, copy_marker, &[])
                            && clippy::implements_trait(cx, duped_type, dupe_trait, &[])
                        {
                            emit_lint(cx, GAZEBO_LINT_DUPE_ON_COPY, method_span);
                        }

                        // Note that Dupe can work on references, that is calling `dupe` on `&Foo`
                        // could also be a valid `dupe` call. So, try de-referencing the type once
                        // and check for `Copy` on `Foo` as well.
                        if let TyKind::Ref(_, inner_ty, _) = duped_type.kind() {
                            duped_type = inner_ty;
                        } else {
                            break;
                        }
                    }
                }
            }
        }
    }
}