]> git.lizzy.rs Git - rust.git/commitdiff
effective visibility: Satisfy borrow checker to use resolver lazily from a closure
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Fri, 18 Nov 2022 22:52:49 +0000 (01:52 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Wed, 23 Nov 2022 21:03:51 +0000 (00:03 +0300)
compiler/rustc_middle/src/middle/privacy.rs
compiler/rustc_resolve/src/effective_visibilities.rs

index 3a91522d362298400438eb5ee0446c2f10522d7c..decd213763d9c860a39f6862b294e388b60c7c3e 100644 (file)
@@ -142,13 +142,13 @@ pub fn update_eff_vis(
     pub fn set_public_at_level(
         &mut self,
         id: LocalDefId,
-        default_vis: impl FnOnce() -> Visibility,
+        lazy_private_vis: impl FnOnce() -> Visibility,
         level: Level,
     ) {
         let mut effective_vis = self
             .effective_vis(id)
             .copied()
-            .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis()));
+            .unwrap_or_else(|| EffectiveVisibility::from_vis(lazy_private_vis()));
         for l in Level::all_levels() {
             if l <= level {
                 *effective_vis.at_level_mut(l) = Visibility::Public;
@@ -206,6 +206,11 @@ pub fn check_invariants(&self, tcx: TyCtxt<'_>, early: bool) {
     }
 }
 
+pub trait IntoDefIdTree {
+    type Tree: DefIdTree;
+    fn tree(self) -> Self::Tree;
+}
+
 impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
     pub fn iter(&self) -> impl Iterator<Item = (&Id, &EffectiveVisibility)> {
         self.map.iter()
@@ -217,21 +222,26 @@ pub fn effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> {
 
     // `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(
+    pub fn update<T: IntoDefIdTree>(
         &mut self,
         id: Id,
         nominal_vis: Visibility,
-        default_vis: Visibility,
+        lazy_private_vis: impl FnOnce(T) -> (Visibility, T),
         inherited_eff_vis: Option<EffectiveVisibility>,
         level: Level,
-        tree: impl DefIdTree,
+        mut into_tree: T,
     ) -> bool {
         let mut changed = false;
-        let mut current_effective_vis = self
-            .map
-            .get(&id)
-            .copied()
-            .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis));
+        let mut current_effective_vis = match self.map.get(&id).copied() {
+            Some(eff_vis) => eff_vis,
+            None => {
+                let private_vis;
+                (private_vis, into_tree) = lazy_private_vis(into_tree);
+                EffectiveVisibility::from_vis(private_vis)
+            }
+        };
+        let tree = into_tree.tree();
+
         if let Some(inherited_effective_vis) = inherited_eff_vis {
             let mut inherited_effective_vis_at_prev_level =
                 *inherited_effective_vis.at_level(level);
index 82dcc7efb1bafce5082b07f045342b366ae07bb6..57fb1fa938935fdd98ff0875afad33f94cf361df 100644 (file)
@@ -7,7 +7,8 @@
 use rustc_data_structures::intern::Interned;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::def_id::CRATE_DEF_ID;
-use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
+use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility};
+use rustc_middle::middle::privacy::{IntoDefIdTree, Level};
 use rustc_middle::ty::Visibility;
 
 type ImportId<'a> = Interned<'a, NameBinding<'a>>;
@@ -29,6 +30,7 @@ fn level(self) -> Level {
 
 pub struct EffectiveVisibilitiesVisitor<'r, 'a> {
     r: &'r mut Resolver<'a>,
+    def_effective_visibilities: EffectiveVisibilities,
     /// While walking import chains we need to track effective visibilities per-binding, and def id
     /// keys in `Resolver::effective_visibilities` are not enough for that, because multiple
     /// bindings can correspond to a single def id in imports. So we keep a separate table.
@@ -36,6 +38,19 @@ pub struct EffectiveVisibilitiesVisitor<'r, 'a> {
     changed: bool,
 }
 
+impl Resolver<'_> {
+    fn nearest_normal_mod(&mut self, def_id: LocalDefId) -> LocalDefId {
+        self.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local()
+    }
+}
+
+impl<'a, 'b> IntoDefIdTree for &'b mut Resolver<'a> {
+    type Tree = &'b Resolver<'a>;
+    fn tree(self) -> Self::Tree {
+        self
+    }
+}
+
 impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
     /// Fills the `Resolver::effective_visibilities` table with public & exported items
     /// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we
@@ -43,6 +58,7 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
     pub fn compute_effective_visibilities<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) {
         let mut visitor = EffectiveVisibilitiesVisitor {
             r,
+            def_effective_visibilities: Default::default(),
             import_effective_visibilities: Default::default(),
             changed: false,
         };
@@ -54,6 +70,7 @@ pub fn compute_effective_visibilities<'c>(r: &'r mut Resolver<'a>, krate: &'c Cr
             visitor.changed = false;
             visit::walk_crate(&mut visitor, krate);
         }
+        visitor.r.effective_visibilities = visitor.def_effective_visibilities;
 
         // Update visibilities for import def ids. These are not used during the
         // `EffectiveVisibilitiesVisitor` pass, because we have more detailed binding-based
@@ -90,10 +107,6 @@ pub fn compute_effective_visibilities<'c>(r: &'r mut Resolver<'a>, krate: &'c Cr
         info!("resolve::effective_visibilities: {:#?}", r.effective_visibilities);
     }
 
-    fn nearest_normal_mod(&mut self, def_id: LocalDefId) -> LocalDefId {
-        self.r.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local()
-    }
-
     /// Update effective visibilities of bindings in the given module,
     /// including their whole reexport chains.
     fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) {
@@ -124,7 +137,7 @@ fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) {
 
     fn effective_vis(&self, parent_id: ParentId<'a>) -> Option<EffectiveVisibility> {
         match parent_id {
-            ParentId::Def(def_id) => self.r.effective_visibilities.effective_vis(def_id),
+            ParentId::Def(def_id) => self.def_effective_visibilities.effective_vis(def_id),
             ParentId::Import(binding) => self.import_effective_visibilities.effective_vis(binding),
         }
         .copied()
@@ -150,7 +163,7 @@ fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) {
         let default_vis = Visibility::Restricted(
             import
                 .id()
-                .map(|id| self.nearest_normal_mod(self.r.local_def_id(id)))
+                .map(|id| self.r.nearest_normal_mod(self.r.local_def_id(id)))
                 .unwrap_or(CRATE_DEF_ID),
         );
         if self.is_noop_update(parent_id, nominal_vis, default_vis) {
@@ -159,25 +172,25 @@ fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) {
         self.changed |= self.import_effective_visibilities.update(
             binding,
             nominal_vis,
-            default_vis,
+            |r| (default_vis, r),
             self.effective_vis(parent_id),
             parent_id.level(),
-            ResolverTree(&self.r.definitions, &self.r.crate_loader),
+            &mut *self.r,
         );
     }
 
     fn update_def(&mut self, def_id: LocalDefId, nominal_vis: Visibility, parent_id: ParentId<'a>) {
-        let default_vis = Visibility::Restricted(self.nearest_normal_mod(def_id));
+        let default_vis = Visibility::Restricted(self.r.nearest_normal_mod(def_id));
         if self.is_noop_update(parent_id, nominal_vis, default_vis) {
             return;
         }
-        self.changed |= self.r.effective_visibilities.update(
+        self.changed |= self.def_effective_visibilities.update(
             def_id,
             nominal_vis,
-            if def_id == CRATE_DEF_ID { Visibility::Public } else { default_vis },
+            |r| (if def_id == CRATE_DEF_ID { Visibility::Public } else { default_vis }, r),
             self.effective_vis(parent_id),
             parent_id.level(),
-            ResolverTree(&self.r.definitions, &self.r.crate_loader),
+            &mut *self.r,
         );
     }