diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index ba42eae344158..3fe2edacf4383 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1424,8 +1424,24 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { } fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { - if matches!(cx.tcx.parent_hir_node(field.hir_id), Node::Variant(_)) { - return; + match cx.tcx.parent_hir_node(field.hir_id) { + Node::Variant(_) => return, + // We don't want to lint on struct/union fields whose parent def is + // not public. We therefore check if the parent is a struct/union and + // if it `pub` we ignore the field. + // + // ``` + // pub(crate) struct Hydrogen { + // pub neutrons: usize, // should not lint + // } + // ``` + Node::Item(item) + if item.is_struct_or_union() + && !cx.tcx.visibility(item.owner_id.def_id).is_public() => + { + return; + } + _ => {} } self.perform_lint(cx, "field", field.def_id, field.vis_span, false); } diff --git a/tests/ui/lint/unreachable_pub.rs b/tests/ui/lint/unreachable_pub.rs index 22c091e112be3..117cbe6238291 100644 --- a/tests/ui/lint/unreachable_pub.rs +++ b/tests/ui/lint/unreachable_pub.rs @@ -15,6 +15,10 @@ mod private_mod { // (... but not more-restricted fields) pub(crate) electrons: usize } + pub(crate) struct Hydrogen { + pub neutrons: usize, // the visibility is clearly defined by the struct above + // no need to cluter the field definition + } impl Hydrogen { // impls, too pub fn count_neutrons(&self) -> usize { self.neutrons } //~ WARNING unreachable_pub