From 1b2c64d223625e53556a520b1ddd4b8265ee671b Mon Sep 17 00:00:00 2001 From: Lamb Date: Tue, 11 Jan 2022 20:09:31 +0000 Subject: [PATCH] fix: set struct/union/enum fields/variants as reachable when item is --- compiler/rustc_privacy/src/lib.rs | 84 +++++++++++++++----- src/test/ui/privacy/auxiliary/issue-92755.rs | 17 ++++ src/test/ui/privacy/issue-92755.rs | 10 +++ 3 files changed, 91 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/privacy/auxiliary/issue-92755.rs create mode 100644 src/test/ui/privacy/issue-92755.rs diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 45da5f81224..e7741ccc4e4 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -652,12 +652,73 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { _ => self.get(item.def_id), }; + // Update levels of nested things. + match item.kind { + hir::ItemKind::Enum(ref def, _) => { + for variant in def.variants { + let variant_level = self.update_with_hir_id(variant.id, item_level); + if let Some(ctor_hir_id) = variant.data.ctor_hir_id() { + self.update_with_hir_id(ctor_hir_id, item_level); + } + for field in variant.data.fields() { + self.update_with_hir_id(field.hir_id, variant_level); + } + } + } + hir::ItemKind::Impl(ref impl_) => { + for impl_item_ref in impl_.items { + if impl_.of_trait.is_some() + || self.tcx.visibility(impl_item_ref.id.def_id) == ty::Visibility::Public + { + self.update(impl_item_ref.id.def_id, item_level); + } + } + } + hir::ItemKind::Trait(.., trait_item_refs) => { + for trait_item_ref in trait_item_refs { + self.update(trait_item_ref.id.def_id, item_level); + } + } + hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => { + if let Some(ctor_hir_id) = def.ctor_hir_id() { + self.update_with_hir_id(ctor_hir_id, item_level); + } + for field in def.fields() { + if field.vis.node.is_pub() { + self.update_with_hir_id(field.hir_id, item_level); + } + } + } + hir::ItemKind::Macro(ref macro_def) => { + self.update_reachability_from_macro(item.def_id, macro_def); + } + hir::ItemKind::ForeignMod { items, .. } => { + for foreign_item in items { + if self.tcx.visibility(foreign_item.id.def_id) == ty::Visibility::Public { + self.update(foreign_item.id.def_id, item_level); + } + } + } + + hir::ItemKind::OpaqueTy(..) + | hir::ItemKind::Use(..) + | hir::ItemKind::Static(..) + | hir::ItemKind::Const(..) + | hir::ItemKind::GlobalAsm(..) + | hir::ItemKind::TyAlias(..) + | hir::ItemKind::Mod(..) + | hir::ItemKind::TraitAlias(..) + | hir::ItemKind::Fn(..) + | hir::ItemKind::ExternCrate(..) => {} + } + // Mark all items in interfaces of reachable items as reachable. match item.kind { // The interface is empty. - hir::ItemKind::ExternCrate(..) => {} + hir::ItemKind::Macro(..) | hir::ItemKind::ExternCrate(..) => {} // All nested items are checked by `visit_item`. hir::ItemKind::Mod(..) => {} + // Handled in the access level of in rustc_resolve hir::ItemKind::Use(..) => {} // The interface is empty. hir::ItemKind::GlobalAsm(..) => {} @@ -709,14 +770,6 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } // Visit everything except for private impl items. hir::ItemKind::Impl(ref impl_) => { - for impl_item_ref in impl_.items { - if impl_.of_trait.is_some() - || self.tcx.visibility(impl_item_ref.id.def_id) == ty::Visibility::Public - { - self.update(impl_item_ref.id.def_id, item_level); - } - } - if item_level.is_some() { self.reach(item.def_id, item_level).generics().predicates().ty().trait_ref(); @@ -731,21 +784,15 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } } } + // Visit everything, but enum variants have their own levels. hir::ItemKind::Enum(ref def, _) => { if item_level.is_some() { self.reach(item.def_id, item_level).generics().predicates(); } - - let enum_level = self.get(item.def_id); for variant in def.variants { - let variant_level = self.update_with_hir_id(variant.id, enum_level); - + let variant_level = self.get(self.tcx.hir().local_def_id(variant.id)); if variant_level.is_some() { - if let Some(ctor_id) = variant.data.ctor_hir_id() { - self.update_with_hir_id(ctor_id, variant_level); - } - for field in variant.data.fields() { self.reach(self.tcx.hir().local_def_id(field.hir_id), variant_level) .ty(); @@ -756,9 +803,6 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } } } - hir::ItemKind::Macro(ref macro_def) => { - self.update_reachability_from_macro(item.def_id, macro_def); - } // Visit everything, but foreign items have their own levels. hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { diff --git a/src/test/ui/privacy/auxiliary/issue-92755.rs b/src/test/ui/privacy/auxiliary/issue-92755.rs new file mode 100644 index 00000000000..6f85273461a --- /dev/null +++ b/src/test/ui/privacy/auxiliary/issue-92755.rs @@ -0,0 +1,17 @@ +mod machine { + pub struct A { + pub b: B, + } + pub struct B {} + impl B { + pub fn f(&self) {} + } +} + +pub struct Context { + pub a: machine::A, +} + +pub fn ctx() -> Context { + todo!(); +} diff --git a/src/test/ui/privacy/issue-92755.rs b/src/test/ui/privacy/issue-92755.rs new file mode 100644 index 00000000000..49559152b6f --- /dev/null +++ b/src/test/ui/privacy/issue-92755.rs @@ -0,0 +1,10 @@ +// aux-build:issue-92755.rs +// build-pass + +// Thank you @tmiasko for providing the content of this test! + +extern crate issue_92755; + +fn main() { + issue_92755::ctx().a.b.f(); +}