From 86add5dbc90864856456c79dadbbc889dcdffc6a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 7 May 2026 20:30:27 +0300 Subject: [PATCH 1/3] resolve: Pass correct parent module when creating `self_decl` --- compiler/rustc_resolve/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 4352e10462901..95664b47b6963 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1565,7 +1565,7 @@ impl<'ra> ResolverArenas<'ra> { vis, span, LocalExpnId::ROOT, - None, + parent, )), ModuleKind::Block => None, }; From 34329d300655272845e3c18d6fa11c63ebdfebcf Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 7 May 2026 20:40:29 +0300 Subject: [PATCH 2/3] resolve: Evaluate private visibilities eagerly in eff vis computation --- compiler/rustc_middle/src/middle/privacy.rs | 4 +- compiler/rustc_privacy/src/lib.rs | 2 +- .../src/effective_visibilities.rs | 56 +++++++++++-------- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index 5a46b6405021d..a5e6e4dd011ed 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -226,13 +226,13 @@ impl EffectiveVisibilities { &mut self, id: Id, max_vis: Option, - lazy_private_vis: impl FnOnce() -> Visibility, + private_vis: Visibility, inherited_effective_vis: EffectiveVisibility, level: Level, tcx: TyCtxt<'_>, ) -> bool { let mut changed = false; - let current_effective_vis = self.effective_vis_or_private(id, lazy_private_vis); + let current_effective_vis = self.effective_vis_or_private(id, || private_vis); let mut inherited_effective_vis_at_prev_level = *inherited_effective_vis.at_level(level); let mut calculated_effective_vis = inherited_effective_vis_at_prev_level; diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index ba30dfccc33cc..d92944d1b31fa 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -476,7 +476,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { self.changed |= self.effective_visibilities.update( def_id, max_vis, - || private_vis, + private_vis, inherited_effective_vis, level, self.tcx, diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 693e49995c1cc..5957c22d76d2e 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -38,20 +38,18 @@ pub(crate) struct EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { } impl Resolver<'_, '_> { - fn nearest_normal_mod(&self, def_id: LocalDefId) -> LocalDefId { - self.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local() - } - - fn private_vis_import(&self, decl: Decl<'_>) -> Visibility { - let DeclKind::Import { import, .. } = decl.kind else { unreachable!() }; + fn private_vis_decl(&self, decl: Decl<'_>) -> Visibility { Visibility::Restricted( - import.def_id().map(|id| self.nearest_normal_mod(id)).unwrap_or(CRATE_DEF_ID), + decl.parent_module.map_or(CRATE_DEF_ID, |m| m.nearest_parent_mod().expect_local()), ) } fn private_vis_def(&self, def_id: LocalDefId) -> Visibility { - // For mod items `nearest_normal_mod` returns its argument, but we actually need its parent. - let normal_mod_id = self.nearest_normal_mod(def_id); + // For mod items `normal_mod_id` will be equal to `def_id`, but we actually need its parent. + let normal_mod_id = self + .get_nearest_non_block_module(def_id.to_def_id()) + .nearest_parent_mod() + .expect_local(); if normal_mod_id == def_id { Visibility::Restricted(self.tcx.local_parent(def_id)) } else { @@ -117,15 +115,23 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { // Set the given effective visibility level to `Level::Direct` and // sets the rest of the `use` chain to `Level::Reexported` until // we hit the actual exported item. + let orig_private_vis = self.current_private_vis; let mut parent_id = ParentId::Def(module_id); while let DeclKind::Import { source_decl, .. } = decl.kind { + if matches!(parent_id, ParentId::Import(_)) { + self.current_private_vis = self.r.private_vis_decl(decl); + } self.update_import(decl, parent_id); parent_id = ParentId::Import(decl); decl = source_decl; } if let Some(def_id) = decl.res().opt_def_id().and_then(|id| id.as_local()) { + if matches!(parent_id, ParentId::Import(_)) { + self.current_private_vis = self.r.private_vis_decl(decl); + } self.update_def(def_id, decl.vis().expect_local(), parent_id); } + self.current_private_vis = orig_private_vis; } } @@ -138,7 +144,7 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { .effective_vis_or_private(def_id, || self.r.private_vis_def(def_id)), ParentId::Import(binding) => self .import_effective_visibilities - .effective_vis_or_private(binding, || self.r.private_vis_import(binding)), + .effective_vis_or_private(binding, || self.r.private_vis_decl(binding)), } } @@ -153,28 +159,30 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { /// /// `None` is returned if the update can be skipped, /// and cheap private visibility is returned otherwise. - fn may_update( - &self, - nominal_vis: Visibility, - parent_id: ParentId<'_>, - ) -> Option> { + fn may_update(&self, nominal_vis: Visibility, parent_id: ParentId<'_>) -> bool { match parent_id { - ParentId::Def(def_id) => (nominal_vis != self.current_private_vis - && self.r.tcx.local_visibility(def_id) != self.current_private_vis) - .then_some(Some(self.current_private_vis)), - ParentId::Import(_) => Some(None), + ParentId::Def(def_id) => { + nominal_vis != self.current_private_vis + && self.r.tcx.local_visibility(def_id) != self.current_private_vis + } + ParentId::Import(decl) => { + nominal_vis != self.current_private_vis + && decl.vis().expect_local() != self.current_private_vis + } } } fn update_import(&mut self, decl: Decl<'ra>, parent_id: ParentId<'ra>) { let nominal_vis = decl.vis().expect_local(); - let Some(cheap_private_vis) = self.may_update(nominal_vis, parent_id) else { return }; + if !self.may_update(nominal_vis, parent_id) { + return; + }; let inherited_eff_vis = self.effective_vis_or_private(parent_id); let tcx = self.r.tcx; self.changed |= self.import_effective_visibilities.update( decl, Some(nominal_vis), - || cheap_private_vis.unwrap_or_else(|| self.r.private_vis_import(decl)), + self.current_private_vis, inherited_eff_vis, parent_id.level(), tcx, @@ -191,13 +199,15 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { nominal_vis: Visibility, parent_id: ParentId<'ra>, ) { - let Some(cheap_private_vis) = self.may_update(nominal_vis, parent_id) else { return }; + if !self.may_update(nominal_vis, parent_id) { + return; + }; let inherited_eff_vis = self.effective_vis_or_private(parent_id); let tcx = self.r.tcx; self.changed |= self.def_effective_visibilities.update( def_id, Some(nominal_vis), - || cheap_private_vis.unwrap_or_else(|| self.r.private_vis_def(def_id)), + self.current_private_vis, inherited_eff_vis, parent_id.level(), tcx, From 23c7d16dcba89a7dd2eafd57f1264e7aa58f6426 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 8 May 2026 07:59:28 +0300 Subject: [PATCH 3/3] WIP --- .../src/effective_visibilities.rs | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 5957c22d76d2e..eadc4df5f89bd 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -12,14 +12,15 @@ use crate::{Decl, DeclKind, Resolver}; #[derive(Clone, Copy)] enum ParentId<'ra> { - Def(LocalDefId), + DefId(LocalDefId), + Decl(Decl<'ra>), Import(Decl<'ra>), } impl ParentId<'_> { fn level(self) -> Level { match self { - ParentId::Def(_) => Level::Direct, + ParentId::DefId(_) | ParentId::Decl(_) => Level::Direct, ParentId::Import(_) => Level::Reexported, } } @@ -44,7 +45,7 @@ impl Resolver<'_, '_> { ) } - fn private_vis_def(&self, def_id: LocalDefId) -> Visibility { + fn private_vis_def_id(&self, def_id: LocalDefId) -> Visibility { // For mod items `normal_mod_id` will be equal to `def_id`, but we actually need its parent. let normal_mod_id = self .get_nearest_non_block_module(def_id.to_def_id()) @@ -116,7 +117,7 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { // sets the rest of the `use` chain to `Level::Reexported` until // we hit the actual exported item. let orig_private_vis = self.current_private_vis; - let mut parent_id = ParentId::Def(module_id); + let mut parent_id = ParentId::Decl(module.self_decl.unwrap()); while let DeclKind::Import { source_decl, .. } = decl.kind { if matches!(parent_id, ParentId::Import(_)) { self.current_private_vis = self.r.private_vis_decl(decl); @@ -139,12 +140,17 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { // Private nodes are only added to the table for caching, they could be added or removed at // any moment without consequences, so we don't set `changed` to true when adding them. *match parent_id { - ParentId::Def(def_id) => self + ParentId::DefId(def_id) => self .def_effective_visibilities - .effective_vis_or_private(def_id, || self.r.private_vis_def(def_id)), - ParentId::Import(binding) => self + .effective_vis_or_private(def_id, || self.r.private_vis_def_id(def_id)), + ParentId::Decl(decl) => self + .def_effective_visibilities + .effective_vis_or_private(decl.res().def_id().expect_local(), || { + self.r.private_vis_decl(decl) + }), + ParentId::Import(decl) => self .import_effective_visibilities - .effective_vis_or_private(binding, || self.r.private_vis_decl(binding)), + .effective_vis_or_private(decl, || self.r.private_vis_decl(decl)), } } @@ -161,11 +167,11 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { /// and cheap private visibility is returned otherwise. fn may_update(&self, nominal_vis: Visibility, parent_id: ParentId<'_>) -> bool { match parent_id { - ParentId::Def(def_id) => { + ParentId::DefId(def_id) => { nominal_vis != self.current_private_vis && self.r.tcx.local_visibility(def_id) != self.current_private_vis } - ParentId::Import(decl) => { + ParentId::Decl(decl) | ParentId::Import(decl) => { nominal_vis != self.current_private_vis && decl.vis().expect_local() != self.current_private_vis } @@ -215,7 +221,7 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { } fn update_field(&mut self, def_id: LocalDefId, parent_id: LocalDefId) { - self.update_def(def_id, self.r.tcx.local_visibility(def_id), ParentId::Def(parent_id)); + self.update_def(def_id, self.r.tcx.local_visibility(def_id), ParentId::DefId(parent_id)); } }