diff --git a/clippy_lints/src/zero_sized_map_values.rs b/clippy_lints/src/zero_sized_map_values.rs index 22d008de758a..19405df77f75 100644 --- a/clippy_lints/src/zero_sized_map_values.rs +++ b/clippy_lints/src/zero_sized_map_values.rs @@ -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:** /// @@ -33,7 +34,7 @@ declare_clippy_lint! { /// } /// ``` pub ZERO_SIZED_MAP_VALUES, - nursery, + pedantic, "usage of map with zero-sized value type" } @@ -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"); + } } } }