From 5e917a6039fb7894273eccf453c34ad907635920 Mon Sep 17 00:00:00 2001 From: Bryanskiy <ivakin.kir@gmail.com> Date: Tue, 6 Jun 2023 18:26:38 +0300 Subject: [PATCH] increase the accuracy of effective visibilities calculation --- compiler/rustc_privacy/src/lib.rs | 46 +++++++++---------- .../src/effective_visibilities.rs | 2 +- .../effective_visibilities_full_priv.rs | 21 +++++++++ .../effective_visibilities_full_priv.stderr | 26 +++++++++++ 4 files changed, 69 insertions(+), 26 deletions(-) create mode 100644 tests/ui/privacy/effective_visibilities_full_priv.rs create mode 100644 tests/ui/privacy/effective_visibilities_full_priv.stderr diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 0197b99c7db..afd32e38d5b 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -409,8 +409,8 @@ impl VisibilityLike for ty::Visibility { } } -impl VisibilityLike for Option<EffectiveVisibility> { - const MAX: Self = Some(EffectiveVisibility::from_vis(ty::Visibility::Public)); +impl VisibilityLike for EffectiveVisibility { + const MAX: Self = EffectiveVisibility::from_vis(ty::Visibility::Public); // Type inference is very smart sometimes. // It can make an impl reachable even some components of its type or trait are unreachable. // E.g. methods of `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }` @@ -422,13 +422,14 @@ impl VisibilityLike for Option<EffectiveVisibility> { // (which require reaching the `DefId`s in them). const SHALLOW: bool = true; fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self { - if let Some(min) = find.min { - return find - .effective_visibilities - .effective_vis(def_id) - .map(|eff_vis| min.min(*eff_vis, find.tcx)); - } - None + let effective_vis = + find.effective_visibilities.effective_vis(def_id).cloned().unwrap_or_else(|| { + let private_vis = + ty::Visibility::Restricted(find.tcx.parent_module_from_def_id(def_id)); + EffectiveVisibility::from_vis(private_vis) + }); + + effective_vis.min(find.min, find.tcx) } } @@ -766,28 +767,23 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } } hir::ItemKind::Impl(ref impl_) => { - if let Some(item_ev) = Option::<EffectiveVisibility>::of_impl( + let item_ev = EffectiveVisibility::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.update_eff_vis(item.owner_id.def_id, item_ev, None, Level::Direct); - self.reach(item.owner_id.def_id, item_ev) - .generics() - .predicates() - .ty() - .trait_ref(); + self.reach(item.owner_id.def_id, item_ev).generics().predicates().ty().trait_ref(); - 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); + 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); - if let Some(impl_item_ev) = self.get(def_id) { - self.reach(def_id, impl_item_ev).generics().predicates().ty(); - } + if let Some(impl_item_ev) = self.get(def_id) { + self.reach(def_id, impl_item_ev).generics().predicates().ty(); } } } diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 7393bdb388a..4863c9f4790 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -81,7 +81,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { def_effective_visibilities: Default::default(), import_effective_visibilities: Default::default(), current_private_vis: Visibility::Restricted(CRATE_DEF_ID), - changed: false, + changed: true, }; visitor.def_effective_visibilities.update_root(); diff --git a/tests/ui/privacy/effective_visibilities_full_priv.rs b/tests/ui/privacy/effective_visibilities_full_priv.rs new file mode 100644 index 00000000000..cc708917586 --- /dev/null +++ b/tests/ui/privacy/effective_visibilities_full_priv.rs @@ -0,0 +1,21 @@ +#![feature(rustc_attrs)] +#![allow(private_in_public)] + +struct SemiPriv; + +mod m { + #[rustc_effective_visibility] + struct Priv; + //~^ ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + //~| ERROR not in the table + + #[rustc_effective_visibility] + pub fn foo() {} //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + + #[rustc_effective_visibility] + impl crate::SemiPriv { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + pub fn f(_: Priv) {} + } +} + +fn main() {} diff --git a/tests/ui/privacy/effective_visibilities_full_priv.stderr b/tests/ui/privacy/effective_visibilities_full_priv.stderr new file mode 100644 index 00000000000..a856aa20d92 --- /dev/null +++ b/tests/ui/privacy/effective_visibilities_full_priv.stderr @@ -0,0 +1,26 @@ +error: Direct: pub(self), Reexported: pub(self), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + --> $DIR/effective_visibilities_full_priv.rs:8:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + +error: not in the table + --> $DIR/effective_visibilities_full_priv.rs:8:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + --> $DIR/effective_visibilities_full_priv.rs:13:5 + | +LL | pub fn foo() {} + | ^^^^^^^^^^^^ + +error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate) + --> $DIR/effective_visibilities_full_priv.rs:16:5 + | +LL | impl crate::SemiPriv { + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors +