diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 8eabb3a31a5..5b06c7fbcbb 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -474,7 +474,7 @@ fn get(&self, def_id: LocalDefId) -> Option { fn update( &mut self, def_id: LocalDefId, - inherited_effective_vis: Option, + inherited_effective_vis: EffectiveVisibility, level: Level, ) { let nominal_vis = self.tcx.local_visibility(def_id); @@ -484,23 +484,20 @@ fn update( fn update_eff_vis( &mut self, def_id: LocalDefId, - inherited_effective_vis: Option, + inherited_effective_vis: EffectiveVisibility, nominal_vis: Option, level: Level, ) { - if let Some(inherited_effective_vis) = inherited_effective_vis { - let private_vis = - ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id)); - if Some(private_vis) != nominal_vis { - self.changed |= self.effective_visibilities.update( - def_id, - nominal_vis, - || private_vis, - inherited_effective_vis, - level, - self.tcx, - ); - } + let private_vis = ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id)); + if Some(private_vis) != nominal_vis { + self.changed |= self.effective_visibilities.update( + def_id, + nominal_vis, + || private_vis, + inherited_effective_vis, + level, + self.tcx, + ); } } @@ -532,9 +529,13 @@ fn reach_through_impl_trait( // We have to make sure that the items that macros might reference // are reachable, since they might be exported transitively. - fn update_reachability_from_macro(&mut self, local_def_id: LocalDefId, md: &MacroDef) { + fn update_reachability_from_macro( + &mut self, + local_def_id: LocalDefId, + md: &MacroDef, + macro_ev: EffectiveVisibility, + ) { // Non-opaque macros cannot make other items more accessible than they already are. - let hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id); let attrs = self.tcx.hir().attrs(hir_id); if attr::find_transparency(attrs, md.macro_rules).0 != Transparency::Opaque { @@ -554,8 +555,6 @@ fn update_reachability_from_macro(&mut self, local_def_id: LocalDefId, md: &Macr // Since we are starting from an externally visible module, // all the parents in the loop below are also guaranteed to be modules. let mut module_def_id = macro_module_def_id; - // If the macro eff vis is not in the table the condition above will return. - let macro_ev = self.get(local_def_id).unwrap(); loop { let changed_reachability = self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev); @@ -620,12 +619,12 @@ fn update_macro_reachable_def( module: LocalDefId, macro_ev: EffectiveVisibility, ) { - self.update(def_id, Some(macro_ev), Level::Reachable); + self.update(def_id, macro_ev, Level::Reachable); match def_kind { // No type privacy, so can be directly marked as reachable. DefKind::Const | DefKind::Static(_) | DefKind::TraitAlias | DefKind::TyAlias => { if vis.is_accessible_from(module, self.tcx) { - self.update(def_id, Some(macro_ev), Level::Reachable); + self.update(def_id, macro_ev, Level::Reachable); } } @@ -637,7 +636,7 @@ fn update_macro_reachable_def( let item = self.tcx.hir().expect_item(def_id); if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }, _) = item.kind { if vis.is_accessible_from(module, self.tcx) { - self.update(def_id, Some(macro_ev), Level::Reachable); + self.update(def_id, macro_ev, Level::Reachable); } } } @@ -701,86 +700,21 @@ fn update_macro_reachable_def( impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - let item_ev = match item.kind { - hir::ItemKind::Impl { .. } => { - let impl_ev = Option::::of_impl( - item.owner_id.def_id, - self.tcx, - &self.effective_visibilities, - ); - - self.update_eff_vis(item.owner_id.def_id, impl_ev, None, Level::Direct); - impl_ev - } - _ => self.get(item.owner_id.def_id), - }; - - // Update levels of nested things. + // Update levels of nested things and mark all items + // in interfaces of reachable items as reachable. + let item_ev = self.get(item.owner_id.def_id); match item.kind { - hir::ItemKind::Enum(ref def, _) => { - for variant in def.variants { - self.update(variant.def_id, item_ev, Level::Reachable); - let variant_ev = self.get(variant.def_id); - if let Some(ctor_def_id) = variant.data.ctor_def_id() { - self.update(ctor_def_id, variant_ev, Level::Reachable); - } - for field in variant.data.fields() { - self.update(field.def_id, variant_ev, Level::Reachable); - } - } - } - hir::ItemKind::Impl(ref impl_) => { - for impl_item_ref in impl_.items { - let def_id = impl_item_ref.id.owner_id.def_id; - let nominal_vis = - impl_.of_trait.is_none().then(|| self.tcx.local_visibility(def_id)); - self.update_eff_vis(def_id, item_ev, nominal_vis, Level::Direct); - } - } - hir::ItemKind::Trait(.., trait_item_refs) => { - for trait_item_ref in trait_item_refs { - self.update(trait_item_ref.id.owner_id.def_id, item_ev, Level::Reachable); - } - } - hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => { - if let Some(ctor_def_id) = def.ctor_def_id() { - self.update(ctor_def_id, item_ev, Level::Reachable); - } - for field in def.fields() { - self.update(field.def_id, item_ev, Level::Reachable); - } - } - hir::ItemKind::Macro(ref macro_def, _) => { - self.update_reachability_from_macro(item.owner_id.def_id, macro_def); - } - hir::ItemKind::ForeignMod { items, .. } => { - for foreign_item in items { - self.update(foreign_item.id.owner_id.def_id, item_ev, Level::Reachable); - } - } - - 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::Macro(..) | hir::ItemKind::ExternCrate(..) => {} - // All nested items are checked by `visit_item`. + // The interface is empty, and no nested items. + hir::ItemKind::Use(..) + | hir::ItemKind::ExternCrate(..) + | hir::ItemKind::GlobalAsm(..) => {} + // The interface is empty, and all nested items are processed by `visit_item`. hir::ItemKind::Mod(..) => {} - // Handled in `rustc_resolve`. - hir::ItemKind::Use(..) => {} - // The interface is empty. - hir::ItemKind::GlobalAsm(..) => {} + hir::ItemKind::Macro(ref macro_def, _) => { + if let Some(item_ev) = item_ev { + self.update_reachability_from_macro(item.owner_id.def_id, macro_def, item_ev); + } + } hir::ItemKind::OpaqueTy(ref opaque) => { // HACK(jynelson): trying to infer the type of `impl trait` breaks `async-std` (and `pub async fn` in general) // Since rustdoc never needs to do codegen and doesn't care about link-time reachability, @@ -797,7 +731,6 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { .ty(); } } - // Visit everything. hir::ItemKind::Const(..) | hir::ItemKind::Static(..) | hir::ItemKind::Fn(..) @@ -811,9 +744,10 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { self.reach(item.owner_id.def_id, item_ev).generics().predicates(); for trait_item_ref in trait_item_refs { + self.update(trait_item_ref.id.owner_id.def_id, item_ev, Level::Reachable); + let tcx = self.tcx; let mut reach = self.reach(trait_item_ref.id.owner_id.def_id, item_ev); - reach.generics().predicates(); if trait_item_ref.kind == AssocItemKind::Type @@ -831,9 +765,14 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { self.reach(item.owner_id.def_id, item_ev).generics().predicates(); } } - // Visit everything except for private impl items. hir::ItemKind::Impl(ref impl_) => { - if let Some(item_ev) = item_ev { + if let Some(item_ev) = Option::::of_impl( + item.owner_id.def_id, + self.tcx, + &self.effective_visibilities, + ) { + self.update_eff_vis(item.owner_id.def_id, item_ev, None, Level::Direct); + self.reach(item.owner_id.def_id, item_ev) .generics() .predicates() @@ -841,24 +780,32 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { .trait_ref(); for impl_item_ref in impl_.items { - if let Some(impl_item_ev) = self.get(impl_item_ref.id.owner_id.def_id) { - self.reach(impl_item_ref.id.owner_id.def_id, impl_item_ev) - .generics() - .predicates() - .ty(); + let def_id = impl_item_ref.id.owner_id.def_id; + let nominal_vis = + impl_.of_trait.is_none().then(|| self.tcx.local_visibility(def_id)); + self.update_eff_vis(def_id, item_ev, nominal_vis, Level::Direct); + + if let Some(impl_item_ev) = self.get(def_id) { + self.reach(def_id, impl_item_ev).generics().predicates().ty(); } } } } - - // Visit everything, but enum variants have their own levels. hir::ItemKind::Enum(ref def, _) => { if let Some(item_ev) = item_ev { self.reach(item.owner_id.def_id, item_ev).generics().predicates(); } for variant in def.variants { + if let Some(item_ev) = item_ev { + self.update(variant.def_id, item_ev, Level::Reachable); + } + if let Some(variant_ev) = self.get(variant.def_id) { + if let Some(ctor_def_id) = variant.data.ctor_def_id() { + self.update(ctor_def_id, variant_ev, Level::Reachable); + } for field in variant.data.fields() { + self.update(field.def_id, variant_ev, Level::Reachable); self.reach(field.def_id, variant_ev).ty(); } // Corner case: if the variant is reachable, but its @@ -872,7 +819,6 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { } } } - // Visit everything, but foreign items have their own levels. hir::ItemKind::ForeignMod { items, .. } => { for foreign_item in items { if let Some(foreign_item_ev) = self.get(foreign_item.id.owner_id.def_id) { @@ -883,17 +829,20 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { } } } - // Visit everything except for private fields. hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { if let Some(item_ev) = item_ev { self.reach(item.owner_id.def_id, item_ev).generics().predicates(); for field in struct_def.fields() { + self.update(field.def_id, item_ev, Level::Reachable); if let Some(field_ev) = self.get(field.def_id) { self.reach(field.def_id, field_ev).ty(); } } } if let Some(ctor_def_id) = struct_def.ctor_def_id() { + if let Some(item_ev) = item_ev { + self.update(ctor_def_id, item_ev, Level::Reachable); + } if let Some(ctor_ev) = self.get(ctor_def_id) { self.reach(item.owner_id.def_id, ctor_ev).ty(); } @@ -953,7 +902,7 @@ fn visit_def_id( _descr: &dyn fmt::Display, ) -> ControlFlow { if let Some(def_id) = def_id.as_local() { - self.ev.update_eff_vis(def_id, Some(self.effective_vis), None, self.level); + self.ev.update_eff_vis(def_id, self.effective_vis, None, self.level); } ControlFlow::Continue(()) }