about summary refs log tree commit diff
path: root/compiler/rustc_middle
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-10-16 20:34:38 +0000
committerbors <bors@rust-lang.org>2022-10-16 20:34:38 +0000
commitb8b5caee04116c7383eb1c6470fcf15c437a60d4 (patch)
tree7e8d5009eeef6799f29e49f9caee86d83121f7fe /compiler/rustc_middle
parentbf286a82e236e065c67909657e3a35d1511d1864 (diff)
parent496ccd982ce155d8f4026eb69c6af1a2b6b5628a (diff)
downloadrust-b8b5caee04116c7383eb1c6470fcf15c437a60d4.tar.gz
rust-b8b5caee04116c7383eb1c6470fcf15c437a60d4.zip
Auto merge of #102026 - Bryanskiy:resolve_update, r=petrochenkov
Populate effective visibilities in 'rustc_resolve'

Next part of RFC https://github.com/rust-lang/rust/issues/48054.
previous: https://github.com/rust-lang/rust/pull/101713

`@rustbot` author
r? `@petrochenkov`
Diffstat (limited to 'compiler/rustc_middle')
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs136
1 files changed, 104 insertions, 32 deletions
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index c595fbec0dd..556bd24d00f 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -1,12 +1,12 @@
 //! A pass that checks to make sure private fields and methods aren't used
 //! outside their scopes. This pass will also generate a set of exported items
 //! which are available for use externally when compiled as a library.
-use crate::ty::Visibility;
+use crate::ty::{DefIdTree, Visibility};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_macros::HashStable;
 use rustc_query_system::ich::StableHashingContext;
-use rustc_span::def_id::LocalDefId;
+use rustc_span::def_id::{DefId, LocalDefId};
 use std::hash::Hash;
 
 /// Represents the levels of accessibility an item can have.
@@ -27,26 +27,36 @@ pub enum AccessLevel {
     Public,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Default)]
+impl AccessLevel {
+    pub fn all_levels() -> [AccessLevel; 4] {
+        [
+            AccessLevel::Public,
+            AccessLevel::Exported,
+            AccessLevel::Reachable,
+            AccessLevel::ReachableFromImplTrait,
+        ]
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)]
 pub struct EffectiveVisibility {
-    public: Option<Visibility>,
-    exported: Option<Visibility>,
-    reachable: Option<Visibility>,
-    reachable_from_impl_trait: Option<Visibility>,
+    public: Visibility,
+    exported: Visibility,
+    reachable: Visibility,
+    reachable_from_impl_trait: Visibility,
 }
 
 impl EffectiveVisibility {
-    pub fn get(&self, tag: AccessLevel) -> Option<&Visibility> {
+    pub fn get(&self, tag: AccessLevel) -> &Visibility {
         match tag {
             AccessLevel::Public => &self.public,
             AccessLevel::Exported => &self.exported,
             AccessLevel::Reachable => &self.reachable,
             AccessLevel::ReachableFromImplTrait => &self.reachable_from_impl_trait,
         }
-        .as_ref()
     }
 
-    fn get_mut(&mut self, tag: AccessLevel) -> &mut Option<Visibility> {
+    fn get_mut(&mut self, tag: AccessLevel) -> &mut Visibility {
         match tag {
             AccessLevel::Public => &mut self.public,
             AccessLevel::Exported => &mut self.exported,
@@ -56,7 +66,30 @@ impl EffectiveVisibility {
     }
 
     pub fn is_public_at_level(&self, tag: AccessLevel) -> bool {
-        self.get(tag).map_or(false, |vis| vis.is_public())
+        self.get(tag).is_public()
+    }
+
+    fn update(&mut self, vis: Visibility, tag: AccessLevel, tree: impl DefIdTree) -> bool {
+        let mut changed = false;
+        for level in AccessLevel::all_levels() {
+            if level <= tag {
+                let current_effective_vis = self.get_mut(level);
+                if *current_effective_vis != vis && vis.is_at_least(*current_effective_vis, tree) {
+                    changed = true;
+                    *current_effective_vis = vis;
+                }
+            }
+        }
+        changed
+    }
+
+    fn from_vis(vis: Visibility) -> EffectiveVisibility {
+        EffectiveVisibility {
+            public: vis,
+            exported: vis,
+            reachable: vis,
+            reachable_from_impl_trait: vis,
+        }
     }
 }
 
@@ -89,12 +122,7 @@ impl<Id: Hash + Eq + Copy> AccessLevels<Id> {
 
     pub fn get_access_level(&self, id: Id) -> Option<AccessLevel> {
         self.get_effective_vis(id).and_then(|effective_vis| {
-            for level in [
-                AccessLevel::Public,
-                AccessLevel::Exported,
-                AccessLevel::Reachable,
-                AccessLevel::ReachableFromImplTrait,
-            ] {
+            for level in AccessLevel::all_levels() {
                 if effective_vis.is_public_at_level(level) {
                     return Some(level);
                 }
@@ -103,21 +131,6 @@ impl<Id: Hash + Eq + Copy> AccessLevels<Id> {
         })
     }
 
-    pub fn set_access_level(&mut self, id: Id, tag: AccessLevel) {
-        let mut effective_vis = self.get_effective_vis(id).copied().unwrap_or_default();
-        for level in [
-            AccessLevel::Public,
-            AccessLevel::Exported,
-            AccessLevel::Reachable,
-            AccessLevel::ReachableFromImplTrait,
-        ] {
-            if level <= tag {
-                *effective_vis.get_mut(level) = Some(Visibility::Public);
-            }
-        }
-        self.map.insert(id, effective_vis);
-    }
-
     pub fn get_effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> {
         self.map.get(&id)
     }
@@ -129,6 +142,65 @@ impl<Id: Hash + Eq + Copy> AccessLevels<Id> {
     pub fn map_id<OutId: Hash + Eq + Copy>(&self, f: impl Fn(Id) -> OutId) -> AccessLevels<OutId> {
         AccessLevels { map: self.map.iter().map(|(k, v)| (f(*k), *v)).collect() }
     }
+
+    pub fn set_access_level(
+        &mut self,
+        id: Id,
+        default_vis: impl FnOnce() -> Visibility,
+        tag: AccessLevel,
+    ) {
+        let mut effective_vis = self
+            .get_effective_vis(id)
+            .copied()
+            .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis()));
+        for level in AccessLevel::all_levels() {
+            if level <= tag {
+                *effective_vis.get_mut(level) = Visibility::Public;
+            }
+        }
+        self.map.insert(id, effective_vis);
+    }
+}
+
+impl<Id: Hash + Eq + Copy + Into<DefId>> AccessLevels<Id> {
+    // `parent_id` is not necessarily a parent in source code tree,
+    // it is the node from which the maximum effective visibility is inherited.
+    pub fn update(
+        &mut self,
+        id: Id,
+        nominal_vis: Visibility,
+        default_vis: impl FnOnce() -> Visibility,
+        parent_id: Id,
+        tag: AccessLevel,
+        tree: impl DefIdTree,
+    ) -> Result<bool, ()> {
+        let mut changed = false;
+        let mut current_effective_vis = self
+            .get_effective_vis(id)
+            .copied()
+            .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis()));
+        if let Some(inherited_effective_vis) = self.get_effective_vis(parent_id) {
+            for level in AccessLevel::all_levels() {
+                if tag >= level {
+                    let inherited_effective_vis_at_level = *inherited_effective_vis.get(level);
+                    let calculated_effective_vis =
+                        if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) {
+                            inherited_effective_vis_at_level
+                        } else {
+                            nominal_vis
+                        };
+                    changed |= current_effective_vis.update(calculated_effective_vis, level, tree);
+                }
+            }
+        } else {
+            if !id.into().is_crate_root() {
+                return Err(());
+            }
+            changed |= current_effective_vis.update(Visibility::Public, AccessLevel::Public, tree);
+        }
+        self.map.insert(id, current_effective_vis);
+        Ok(changed)
+    }
 }
 
 impl<Id> Default for AccessLevels<Id> {