Skip to content

Commit 9e50375

Browse files
committed
initial commit for effective vis table impl in rustc_resolve
1 parent efa717b commit 9e50375

File tree

2 files changed

+87
-7
lines changed

2 files changed

+87
-7
lines changed

compiler/rustc_middle/src/middle/privacy.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! A pass that checks to make sure private fields and methods aren't used
22
//! outside their scopes. This pass will also generate a set of exported items
33
//! which are available for use externally when compiled as a library.
4-
use crate::ty::Visibility;
4+
use crate::ty::{Visibility, DefIdTree};
55
use rustc_data_structures::fx::FxHashMap;
66
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
77
use rustc_macros::HashStable;
@@ -58,6 +58,35 @@ impl EffectiveVisibility {
5858
pub fn is_public_at_level(&self, tag: AccessLevel) -> bool {
5959
self.get(tag).map_or(false, |vis| vis.is_public())
6060
}
61+
62+
pub fn nearest_available(&self, tag: AccessLevel) -> Option<Visibility> {
63+
for level in [AccessLevel::ReachableFromImplTrait, AccessLevel::Reachable, AccessLevel::Exported, AccessLevel::Public] {
64+
if (level <= tag) && self.get(tag).is_some() {
65+
return self.get(tag).cloned();
66+
}
67+
}
68+
None
69+
}
70+
71+
pub fn update<T: DefIdTree>(&mut self, vis: Visibility, tag: AccessLevel, tree: T) {
72+
for level in [
73+
AccessLevel::Public,
74+
AccessLevel::Exported,
75+
AccessLevel::Reachable,
76+
AccessLevel::ReachableFromImplTrait,
77+
] {
78+
if level <= tag {
79+
let current_effective_vis = self.get_mut(level);
80+
if let Some(current_effective_vis) = current_effective_vis {
81+
if vis.is_at_least(*current_effective_vis, tree) {
82+
*current_effective_vis = vis;
83+
}
84+
} else {
85+
*current_effective_vis = Some(vis);
86+
}
87+
}
88+
}
89+
}
6190
}
6291

6392
/// Holds a map of accessibility levels for reachable HIR nodes.
@@ -122,6 +151,10 @@ impl<Id: Hash + Eq + Copy> AccessLevels<Id> {
122151
self.map.get(&id)
123152
}
124153

154+
pub fn set_effective_vis(&mut self, id: Id, effective_vis: EffectiveVisibility) {
155+
self.map.insert(id, effective_vis);
156+
}
157+
125158
pub fn iter(&self) -> impl Iterator<Item = (&Id, &EffectiveVisibility)> {
126159
self.map.iter()
127160
}

compiler/rustc_resolve/src/access_levels.rs

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_ast::NodeId;
1111
use rustc_hir::def_id::LocalDefId;
1212
use rustc_hir::def_id::CRATE_DEF_ID;
1313
use rustc_middle::middle::privacy::AccessLevel;
14-
use rustc_middle::ty::DefIdTree;
14+
use rustc_middle::ty::{DefIdTree, Visibility};
1515
use rustc_span::sym;
1616

1717
pub struct AccessLevelsVisitor<'r, 'a> {
@@ -26,6 +26,11 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
2626
pub fn compute_access_levels<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) {
2727
let mut visitor = AccessLevelsVisitor { r, changed: false };
2828

29+
/*
30+
let crate_effective_vis = EffectiveVisibility::default();
31+
crate_effective_vis.update(Visibility::Public, AccessLevel::Public, visitor.r);
32+
visitor.r.access_levels.set_effective_vis(CRATE_DEF_ID, crate_effective_vis);
33+
*/
2934
visitor.set_access_level_def_id(CRATE_DEF_ID, Some(AccessLevel::Public));
3035
visitor.set_bindings_access_level(CRATE_DEF_ID);
3136

@@ -47,9 +52,6 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
4752
fn set_bindings_access_level(&mut self, module_id: LocalDefId) {
4853
assert!(self.r.module_map.contains_key(&&module_id.to_def_id()));
4954
let module_level = self.r.access_levels.get_access_level(module_id);
50-
if !module_level.is_some() {
51-
return;
52-
}
5355
// Set the given binding access level to `AccessLevel::Public` and
5456
// sets the rest of the `use` chain to `AccessLevel::Exported` until
5557
// we hit the actual exported item.
@@ -72,8 +74,8 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
7274
let module = self.r.get_module(module_id.to_def_id()).unwrap();
7375
let resolutions = self.r.resolutions(module);
7476

75-
for (.., name_resolution) in resolutions.borrow().iter() {
76-
if let Some(binding) = name_resolution.borrow().binding() && binding.vis.is_public() && !binding.is_ambiguity() {
77+
for (key, name_resolution) in resolutions.borrow().iter() {
78+
if let Some(binding) = name_resolution.borrow().binding() && binding.vis.is_public() && !binding.is_ambiguity() && module_level.is_some() {
7779
let access_level = match binding.is_import() {
7880
true => {
7981
set_import_binding_access_level(self, binding, module_level);
@@ -85,6 +87,51 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
8587
self.set_access_level_def_id(def_id, access_level);
8688
}
8789
}
90+
91+
if let Some(binding) = name_resolution.borrow().binding() {
92+
println!("ident: {}", key.ident.as_str());
93+
if let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) {
94+
let tag = match binding.is_import() {
95+
true => AccessLevel::Exported,
96+
false => AccessLevel::Public,
97+
};
98+
let vis = match binding.vis {
99+
Visibility::Public => Visibility::Public,
100+
Visibility::Restricted(id) => Visibility::Restricted(id.expect_local())
101+
};
102+
self.update_effective_vis(def_id, vis, module_id, tag);
103+
};
104+
}
105+
}
106+
}
107+
108+
// fn init_crate_effective_vis(&mut self) {
109+
110+
// }
111+
112+
fn update_effective_vis(
113+
&mut self,
114+
current_id: LocalDefId,
115+
current_vis: Visibility,
116+
module_id: LocalDefId,
117+
tag: AccessLevel,
118+
) {
119+
if let Some(inherited_effective_vis) = self.r.access_levels.get_effective_vis(module_id) {
120+
println!("tag: {:?}", tag);
121+
println!("inherited effective vis: {:?}", inherited_effective_vis);
122+
let mut current_effective_vis = self.r.access_levels.get_effective_vis(current_id).copied().unwrap_or_default();
123+
let nearest_available_vis = inherited_effective_vis.nearest_available(tag).unwrap();
124+
println!("nearest available vis: {:?}", nearest_available_vis);
125+
let calculated_effective_vis = match current_vis {
126+
Visibility::Public => nearest_available_vis,
127+
Visibility::Restricted(_) => {
128+
if current_vis.is_at_least(nearest_available_vis, &*self.r) {nearest_available_vis} else {current_vis}
129+
}
130+
};
131+
println!("calculated effective vis: {:?}", calculated_effective_vis);
132+
current_effective_vis.update(calculated_effective_vis, tag, &*self.r);
133+
println!("updated effective vis: {:?}", current_effective_vis);
134+
self.r.access_levels.set_effective_vis(current_id, current_effective_vis);
88135
}
89136
}
90137

0 commit comments

Comments
 (0)