diff --git a/clippy_lints/src/exhaustive_items.rs b/clippy_lints/src/exhaustive_items.rs index 436dc8611bde..0f4176ec73bb 100644 --- a/clippy_lints/src/exhaustive_items.rs +++ b/clippy_lints/src/exhaustive_items.rs @@ -70,20 +70,24 @@ declare_lint_pass!(ExhaustiveItems => [EXHAUSTIVE_ENUMS, EXHAUSTIVE_STRUCTS]); impl LateLintPass<'_> for ExhaustiveItems { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { - if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind - && cx.effective_visibilities.is_exported(item.owner_id.def_id) + let (lint, msg, fields) = match item.kind { + ItemKind::Enum(..) => ( + EXHAUSTIVE_ENUMS, + "exported enums should not be exhaustive", + [].as_slice(), + ), + ItemKind::Struct(v, ..) => ( + EXHAUSTIVE_STRUCTS, + "exported structs should not be exhaustive", + v.fields(), + ), + _ => return, + }; + if cx.effective_visibilities.is_exported(item.owner_id.def_id) && let attrs = cx.tcx.hir().attrs(item.hir_id()) && !attrs.iter().any(|a| a.has_name(sym::non_exhaustive)) + && fields.iter().all(|f| cx.tcx.visibility(f.def_id).is_public()) { - let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind { - if v.fields().iter().any(|f| !cx.tcx.visibility(f.def_id).is_public()) { - // skip structs with private fields - return; - } - (EXHAUSTIVE_STRUCTS, "exported structs should not be exhaustive") - } else { - (EXHAUSTIVE_ENUMS, "exported enums should not be exhaustive") - }; let suggestion_span = item.span.shrink_to_lo(); let indent = " ".repeat(indent_of(cx, item.span).unwrap_or(0)); span_lint_and_then(cx, lint, item.span, msg, |diag| {