Skip to content

Commit

Permalink
Move most of implementation into check_ty
Browse files Browse the repository at this point in the history
  • Loading branch information
korrat committed Nov 14, 2020
1 parent e5d8eb2 commit 3320a70
Showing 1 changed file with 18 additions and 89 deletions.
107 changes: 18 additions & 89 deletions clippy_lints/src/zero_sized_map_values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ declare_clippy_lint! {
/// containing zero sized values is effectively a set. Using a set in that case improves
/// readability and communicates intent more clearly.
///
/// **Known problems:** A zero-sized type cannot be recovered later if it contains private
/// fields.
/// **Known problems:**
/// * A zero-sized type cannot be recovered later if it contains private fields.
/// * This lints the signature of public items
///
/// **Example:**
///
Expand All @@ -33,7 +34,7 @@ declare_clippy_lint! {
/// }
/// ```
pub ZERO_SIZED_MAP_VALUES,
nursery,
pedantic,
"usage of map with zero-sized value type"
}

Expand All @@ -46,107 +47,35 @@ impl LateLintPass<'_> for ZeroSizedMapValues {
self.check_ty(cx, ty, local.pat.span);
}

fn check_fn(&mut self, cx: &LateContext<'_>, _: FnKind<'_>, decl: &FnDecl<'_>, _: &Body<'_>, _: Span, id: HirId) {
if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_item(id)) {
fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) {
let parent_id = cx.tcx.hir().get_parent_item(hir_ty.hir_id);
if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_item(parent_id)) {
if let ItemKind::Impl { of_trait: Some(_), .. } = item.kind {
return;
}
}

self.check_fn_decl(cx, decl);
}

fn check_struct_field(&mut self, cx: &LateContext<'_>, field: &StructField<'_>) {
self.check_hir_ty(cx, field.ty);
}

fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) {
match item.kind {
TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => {
self.check_hir_ty(cx, ty);
},
TraitItemKind::Fn(ref sig, _) => {
self.check_fn_decl(cx, &sig.decl);
},
_ => (),
}
}
}

impl ZeroSizedMapValues {
fn check_fn_decl(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>) {
for ty in decl.inputs {
self.check_hir_ty(cx, ty);
}

if let FnRetTy::Return(ty) = decl.output {
self.check_hir_ty(cx, ty);
}
}

fn check_hir_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) {
// TODO this causes errors in some cases
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
self.check_ty(cx, ty, hir_ty.span);

match hir_ty.kind {
TyKind::Path(ref qpath) => match *qpath {
QPath::Resolved(ty, ref p) => {
if let Some(ty) = ty {
self.check_hir_ty(cx, ty);
}

for ty in p.segments.iter().flat_map(|seg| {
seg.args
.as_ref()
.map_or_else(|| [].iter(), |params| params.args.iter())
.filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
_ => None,
})
}) {
self.check_hir_ty(cx, ty);
}
},
QPath::TypeRelative(ty, ref seg) => {
self.check_hir_ty(cx, ty);

if let Some(ref params) = seg.args {
for ty in params.args.iter().filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
_ => None,
}) {
self.check_hir_ty(cx, ty);
}
}
},
QPath::LangItem(..) => {},
},
TyKind::Slice(ref ty) | TyKind::Array(ref ty, _) | TyKind::Ptr(MutTy { ref ty, .. }) => {
self.check_hir_ty(cx, ty);
},
TyKind::Tup(tys) => {
for ty in tys {
self.check_hir_ty(cx, ty);
}
},
_ => {},
}
}
}

impl ZeroSizedMapValues {
fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span) {
if span.from_expansion() {
return;
}

if_chain! {
if match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &paths::BTREEMAP);
if let Adt(_, ref substs) = ty.kind();
let ty = substs.type_at(1);
if let Ok(layout) = cx.layout_of(ty);
if layout.is_zst();
then {
span_lint_and_help(cx, ZERO_SIZED_MAP_VALUES, span, "map with zero-sized value type", None, "consider using a set instead");
}
if match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &paths::BTREEMAP);
if let Adt(_, ref substs) = ty.kind();
let ty = substs.type_at(1);
if let Ok(layout) = cx.layout_of(ty);
if layout.is_zst();
then {
span_lint_and_help(cx, ZERO_SIZED_MAP_VALUES, span, "map with zero-sized value type", None, "consider using a set instead");
}
}
}
}

0 comments on commit 3320a70

Please sign in to comment.