in gazebo_lint/src/lib.rs [423:478]
fn check_impl_dupe(cx: &LateContext, item: &Item) {
fn is_cheap<'tcx>(
cx: &LateContext<'tcx>,
self_tys: rustc_middle::ty::Ty<'tcx>,
dupe_trait: DefId,
) -> bool {
match self_tys.kind() {
TyKind::Adt(self_adt, sub) => {
for variant in self_adt.variants.iter() {
let mut fields = variant.fields.iter();
if let Some(field) = fields.next() {
if fields.next().is_some() {
// only adt's of one field at most one field can be assumed dupe
// we don't want to mark a struct of 100 Arc's as dupe.
return false;
}
let field_ty = field.ty(cx.tcx, sub);
if !clippy::implements_trait(cx, field_ty, dupe_trait, sub) {
// the field isn't dupe, so the whole adt isn't
return false;
}
}
// empty fields => unit, which is dupe
}
// if we survived the loop, we can be dupe.
true
}
_ => false,
}
}
fn is_copy<'tcx>(cx: &LateContext<'tcx>, self_tys: rustc_middle::ty::Ty<'tcx>) -> bool {
if let Some(copy_trait) = clippy::get_trait_def_id(cx, &["core", "marker", "Copy"]) {
clippy::implements_trait(cx, self_tys, copy_trait, &[])
} else {
false
}
}
if let Some(dupe_trait) = clippy::get_trait_def_id(cx, &["gazebo", "dupe", "Dupe"]) {
if let Some(self_tys) =
clippy::is_implementation_of_trait(cx, item, &["core", "clone", "Clone"])
{
if clippy::implements_trait(cx, self_tys, dupe_trait, &[]) {
// already dupe
return;
}
if is_copy(cx, self_tys) || is_cheap(cx, self_tys, dupe_trait) {
emit_lint(cx, GAZEBO_LINT_IMPL_DUPE, item.span);
}
}
}
}