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;
}
}
}
}
}
}
}