diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index ee459d9c129..0bcb0719f9b 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -14,8 +14,8 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID}; -use rustc_hir::intravisit::{self, DeepVisitor, Visitor}; -use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind}; +use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::{AssocItemKind, HirIdSet, ItemId, Node, PatKind}; use rustc_middle::bug; use rustc_middle::hir::nested_filter; use rustc_middle::middle::privacy::{AccessLevel, AccessLevels}; @@ -1802,12 +1802,12 @@ impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { } } -struct PrivateItemsInPublicInterfacesVisitor<'tcx> { +struct PrivateItemsInPublicInterfacesChecker<'tcx> { tcx: TyCtxt<'tcx>, old_error_set_ancestry: LocalDefIdSet, } -impl<'tcx> PrivateItemsInPublicInterfacesVisitor<'tcx> { +impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { fn check( &self, def_id: LocalDefId, @@ -1841,110 +1841,121 @@ impl<'tcx> PrivateItemsInPublicInterfacesVisitor<'tcx> { check.ty(); } } -} -impl<'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'tcx> { - type NestedFilter = nested_filter::OnlyBodies; - - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() - } - - fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { + pub fn check_item(&mut self, id: ItemId) { let tcx = self.tcx; - let item_visibility = tcx.visibility(item.def_id); + let item_visibility = tcx.visibility(id.def_id); + let def_kind = tcx.def_kind(id.def_id); - match item.kind { - // Crates are always public. - hir::ItemKind::ExternCrate(..) => {} - // All nested items are checked by `visit_item`. - hir::ItemKind::Mod(..) => {} - // Checked in resolve. - hir::ItemKind::Use(..) => {} - // No subitems. - hir::ItemKind::Macro(..) | hir::ItemKind::GlobalAsm(..) => {} - // Subitems of these items have inherited publicity. - hir::ItemKind::Const(..) - | hir::ItemKind::Static(..) - | hir::ItemKind::Fn(..) - | hir::ItemKind::TyAlias(..) => { - self.check(item.def_id, item_visibility).generics().predicates().ty(); + if matches!( + def_kind, + DefKind::ExternCrate + | DefKind::Mod + | DefKind::Use + | DefKind::Macro(_) + | DefKind::GlobalAsm + ) { + return; + } + + match def_kind { + DefKind::Const | DefKind::Static(_) | DefKind::Fn | DefKind::TyAlias => { + self.check(id.def_id, item_visibility).generics().predicates().ty(); } - hir::ItemKind::OpaqueTy(..) => { + DefKind::OpaqueTy => { // `ty()` for opaque types is the underlying type, // it's not a part of interface, so we skip it. - self.check(item.def_id, item_visibility).generics().bounds(); + self.check(id.def_id, item_visibility).generics().bounds(); } - hir::ItemKind::Trait(.., trait_item_refs) => { - self.check(item.def_id, item_visibility).generics().predicates(); + DefKind::Trait => { + let item = tcx.hir().item(id); + if let hir::ItemKind::Trait(.., trait_item_refs) = item.kind { + self.check(item.def_id, item_visibility).generics().predicates(); - for trait_item_ref in trait_item_refs { - self.check_assoc_item( - trait_item_ref.id.def_id, - trait_item_ref.kind, - trait_item_ref.defaultness, - item_visibility, - ); + for trait_item_ref in trait_item_refs { + self.check_assoc_item( + trait_item_ref.id.def_id, + trait_item_ref.kind, + trait_item_ref.defaultness, + item_visibility, + ); - if let AssocItemKind::Type = trait_item_ref.kind { - self.check(trait_item_ref.id.def_id, item_visibility).bounds(); + if let AssocItemKind::Type = trait_item_ref.kind { + self.check(trait_item_ref.id.def_id, item_visibility).bounds(); + } } } } - hir::ItemKind::TraitAlias(..) => { - self.check(item.def_id, item_visibility).generics().predicates(); + DefKind::TraitAlias => { + self.check(id.def_id, item_visibility).generics().predicates(); } - hir::ItemKind::Enum(ref def, _) => { - self.check(item.def_id, item_visibility).generics().predicates(); + DefKind::Enum => { + let item = tcx.hir().item(id); + if let hir::ItemKind::Enum(ref def, _) = item.kind { + self.check(item.def_id, item_visibility).generics().predicates(); - for variant in def.variants { - for field in variant.data.fields() { - self.check(self.tcx.hir().local_def_id(field.hir_id), item_visibility).ty(); + for variant in def.variants { + for field in variant.data.fields() { + self.check(self.tcx.hir().local_def_id(field.hir_id), item_visibility) + .ty(); + } } } } // Subitems of foreign modules have their own publicity. - hir::ItemKind::ForeignMod { items, .. } => { - for foreign_item in items { - let vis = tcx.visibility(foreign_item.id.def_id); - self.check(foreign_item.id.def_id, vis).generics().predicates().ty(); + DefKind::ForeignMod => { + let item = tcx.hir().item(id); + if let hir::ItemKind::ForeignMod { items, .. } = item.kind { + for foreign_item in items { + let vis = tcx.visibility(foreign_item.id.def_id); + self.check(foreign_item.id.def_id, vis).generics().predicates().ty(); + } } } // Subitems of structs and unions have their own publicity. - hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { - self.check(item.def_id, item_visibility).generics().predicates(); + DefKind::Struct | DefKind::Union => { + let item = tcx.hir().item(id); + if let hir::ItemKind::Struct(ref struct_def, _) + | hir::ItemKind::Union(ref struct_def, _) = item.kind + { + self.check(item.def_id, item_visibility).generics().predicates(); - for field in struct_def.fields() { - let def_id = tcx.hir().local_def_id(field.hir_id); - let field_visibility = tcx.visibility(def_id); - self.check(def_id, min(item_visibility, field_visibility, tcx)).ty(); + for field in struct_def.fields() { + let def_id = tcx.hir().local_def_id(field.hir_id); + let field_visibility = tcx.visibility(def_id); + self.check(def_id, min(item_visibility, field_visibility, tcx)).ty(); + } } } // An inherent impl is public when its type is public // Subitems of inherent impls have their own publicity. // A trait impl is public when both its type and its trait are public // Subitems of trait impls have inherited publicity. - hir::ItemKind::Impl(ref impl_) => { - let impl_vis = ty::Visibility::of_impl(item.def_id, tcx, &Default::default()); - // check that private components do not appear in the generics or predicates of inherent impls - // this check is intentionally NOT performed for impls of traits, per #90586 - if impl_.of_trait.is_none() { - self.check(item.def_id, impl_vis).generics().predicates(); - } - for impl_item_ref in impl_.items { - let impl_item_vis = if impl_.of_trait.is_none() { - min(tcx.visibility(impl_item_ref.id.def_id), impl_vis, tcx) - } else { - impl_vis - }; - self.check_assoc_item( - impl_item_ref.id.def_id, - impl_item_ref.kind, - impl_item_ref.defaultness, - impl_item_vis, - ); + DefKind::Impl => { + let item = tcx.hir().item(id); + if let hir::ItemKind::Impl(ref impl_) = item.kind { + let impl_vis = ty::Visibility::of_impl(item.def_id, tcx, &Default::default()); + // check that private components do not appear in the generics or predicates of inherent impls + // this check is intentionally NOT performed for impls of traits, per #90586 + if impl_.of_trait.is_none() { + self.check(item.def_id, impl_vis).generics().predicates(); + } + for impl_item_ref in impl_.items { + let impl_item_vis = if impl_.of_trait.is_none() { + min(tcx.visibility(impl_item_ref.id.def_id), impl_vis, tcx) + } else { + impl_vis + }; + self.check_assoc_item( + impl_item_ref.id.def_id, + impl_item_ref.kind, + impl_item_ref.defaultness, + impl_item_vis, + ); + } } } + _ => {} } } } @@ -2069,7 +2080,7 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) { } // Check for private types and traits in public interfaces. - let mut visitor = PrivateItemsInPublicInterfacesVisitor { + let mut checker = PrivateItemsInPublicInterfacesChecker { tcx, // Only definition IDs are ever searched in `old_error_set_ancestry`, // so we can filter away all non-definition IDs at this point. @@ -2078,5 +2089,8 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) { .filter_map(|hir_id| tcx.hir().opt_local_def_id(hir_id)) .collect(), }; - tcx.hir().visit_all_item_likes(&mut DeepVisitor::new(&mut visitor)); + + for id in tcx.hir().items() { + checker.check_item(id); + } }