Skip to content

Commit 36fb140

Browse files
committed
Cleanup visibility.rs
1 parent dc69255 commit 36fb140

File tree

4 files changed

+96
-52
lines changed

4 files changed

+96
-52
lines changed

crates/hir-def/src/item_tree/lower.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,7 @@ impl<'a> Ctx<'a> {
658658

659659
fn lower_visibility(&mut self, item: &dyn ast::HasVisibility) -> RawVisibilityId {
660660
let vis =
661-
RawVisibility::from_ast_with_span_map(self.db, item.visibility(), self.span_map());
661+
RawVisibility::from_opt_ast_with_span_map(self.db, item.visibility(), self.span_map());
662662
self.data().vis.alloc(vis)
663663
}
664664

crates/hir-def/src/resolver.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ impl Resolver {
248248
RawVisibility::Public => Some(Visibility::Public),
249249
}
250250
}
251+
251252
pub fn resolve_path_in_value_ns(
252253
&self,
253254
db: &dyn DefDatabase,

crates/hir-def/src/visibility.rs

Lines changed: 68 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,14 @@ impl RawVisibility {
3737
db: &dyn DefDatabase,
3838
node: InFile<Option<ast::Visibility>>,
3939
) -> RawVisibility {
40+
let node = match node.transpose() {
41+
None => return RawVisibility::private(),
42+
Some(node) => node,
43+
};
4044
Self::from_ast_with_span_map(db, node.value, db.span_map(node.file_id).as_ref())
4145
}
4246

43-
pub(crate) fn from_ast_with_span_map(
47+
pub(crate) fn from_opt_ast_with_span_map(
4448
db: &dyn DefDatabase,
4549
node: Option<ast::Visibility>,
4650
span_map: SpanMapRef<'_>,
@@ -49,29 +53,28 @@ impl RawVisibility {
4953
None => return RawVisibility::private(),
5054
Some(node) => node,
5155
};
52-
match node.kind() {
56+
Self::from_ast_with_span_map(db, node, span_map)
57+
}
58+
59+
fn from_ast_with_span_map(
60+
db: &dyn DefDatabase,
61+
node: ast::Visibility,
62+
span_map: SpanMapRef<'_>,
63+
) -> RawVisibility {
64+
let path = match node.kind() {
5365
ast::VisibilityKind::In(path) => {
5466
let path = ModPath::from_src(db.upcast(), path, span_map);
55-
let path = match path {
67+
match path {
5668
None => return RawVisibility::private(),
5769
Some(path) => path,
58-
};
59-
RawVisibility::Module(path, VisibilityExplicitness::Explicit)
60-
}
61-
ast::VisibilityKind::PubCrate => {
62-
let path = ModPath::from_kind(PathKind::Crate);
63-
RawVisibility::Module(path, VisibilityExplicitness::Explicit)
64-
}
65-
ast::VisibilityKind::PubSuper => {
66-
let path = ModPath::from_kind(PathKind::Super(1));
67-
RawVisibility::Module(path, VisibilityExplicitness::Explicit)
68-
}
69-
ast::VisibilityKind::PubSelf => {
70-
let path = ModPath::from_kind(PathKind::Super(0));
71-
RawVisibility::Module(path, VisibilityExplicitness::Explicit)
70+
}
7271
}
73-
ast::VisibilityKind::Pub => RawVisibility::Public,
74-
}
72+
ast::VisibilityKind::PubCrate => ModPath::from_kind(PathKind::Crate),
73+
ast::VisibilityKind::PubSuper => ModPath::from_kind(PathKind::Super(1)),
74+
ast::VisibilityKind::PubSelf => ModPath::from_kind(PathKind::Super(0)),
75+
ast::VisibilityKind::Pub => return RawVisibility::Public,
76+
};
77+
RawVisibility::Module(path, VisibilityExplicitness::Explicit)
7578
}
7679

7780
pub fn resolve(
@@ -94,6 +97,10 @@ pub enum Visibility {
9497
}
9598

9699
impl Visibility {
100+
pub(crate) fn is_visible_from_other_crate(self) -> bool {
101+
matches!(self, Visibility::Public)
102+
}
103+
97104
#[tracing::instrument(skip_all)]
98105
pub fn is_visible_from(self, db: &dyn DefDatabase, from_module: ModuleId) -> bool {
99106
let to_module = match self {
@@ -105,45 +112,59 @@ impl Visibility {
105112
return false;
106113
}
107114
let def_map = from_module.def_map(db);
108-
self.is_visible_from_def_map(db, &def_map, from_module.local_id)
109-
}
110-
111-
pub(crate) fn is_visible_from_other_crate(self) -> bool {
112-
matches!(self, Visibility::Public)
115+
Self::is_visible_from_def_map_(db, &def_map, to_module, from_module.local_id)
113116
}
114117

115118
pub(crate) fn is_visible_from_def_map(
116119
self,
117120
db: &dyn DefDatabase,
118121
def_map: &DefMap,
119-
mut from_module: LocalModuleId,
122+
from_module: LocalModuleId,
120123
) -> bool {
121-
let mut to_module = match self {
124+
let to_module = match self {
122125
Visibility::Module(m, _) => m,
123126
Visibility::Public => return true,
124127
};
128+
// if they're not in the same crate, it can't be visible
129+
if def_map.krate() != to_module.krate {
130+
return false;
131+
}
132+
Self::is_visible_from_def_map_(db, def_map, to_module, from_module)
133+
}
125134

135+
fn is_visible_from_def_map_(
136+
db: &dyn DefDatabase,
137+
def_map: &DefMap,
138+
mut to_module: ModuleId,
139+
mut from_module: LocalModuleId,
140+
) -> bool {
141+
debug_assert_eq!(to_module.krate, def_map.krate());
126142
// `to_module` might be the root module of a block expression. Those have the same
127143
// visibility as the containing module (even though no items are directly nameable from
128144
// there, getting this right is important for method resolution).
129145
// In that case, we adjust the visibility of `to_module` to point to the containing module.
130146

131147
// Additional complication: `to_module` might be in `from_module`'s `DefMap`, which we're
132148
// currently computing, so we must not call the `def_map` query for it.
133-
let mut arc;
149+
let def_map_block = def_map.block_id();
134150
loop {
135-
let to_module_def_map =
136-
if to_module.krate == def_map.krate() && to_module.block == def_map.block_id() {
151+
match (to_module.block, def_map_block) {
152+
// to_module is not a block, so there is no parent def map to use
153+
(None, _) => (),
154+
(Some(a), Some(b)) if a == b => {
137155
cov_mark::hit!(is_visible_from_same_block_def_map);
138-
def_map
139-
} else {
140-
arc = to_module.def_map(db);
141-
&arc
142-
};
143-
match to_module_def_map.parent() {
144-
Some(parent) => to_module = parent,
145-
None => break,
156+
if let Some(parent) = def_map.parent() {
157+
to_module = parent;
158+
}
159+
}
160+
_ => {
161+
if let Some(parent) = to_module.def_map(db).parent() {
162+
to_module = parent;
163+
continue;
164+
}
165+
}
146166
}
167+
break;
147168
}
148169

149170
// from_module needs to be a descendant of to_module
@@ -176,30 +197,25 @@ impl Visibility {
176197
/// visible in unrelated modules).
177198
pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> {
178199
match (self, other) {
179-
(Visibility::Module(_, _) | Visibility::Public, Visibility::Public)
180-
| (Visibility::Public, Visibility::Module(_, _)) => Some(Visibility::Public),
181-
(Visibility::Module(mod_a, vis_a), Visibility::Module(mod_b, vis_b)) => {
200+
(_, Visibility::Public) | (Visibility::Public, _) => Some(Visibility::Public),
201+
(Visibility::Module(mod_a, expl_a), Visibility::Module(mod_b, expl_b)) => {
182202
if mod_a.krate != mod_b.krate {
183203
return None;
184204
}
185205

186-
let mut a_ancestors = iter::successors(Some(mod_a.local_id), |&m| {
187-
let parent_id = def_map[m].parent?;
188-
Some(parent_id)
189-
});
190-
let mut b_ancestors = iter::successors(Some(mod_b.local_id), |&m| {
191-
let parent_id = def_map[m].parent?;
192-
Some(parent_id)
193-
});
206+
let mut a_ancestors =
207+
iter::successors(Some(mod_a.local_id), |&m| def_map[m].parent);
208+
let mut b_ancestors =
209+
iter::successors(Some(mod_b.local_id), |&m| def_map[m].parent);
194210

195211
if a_ancestors.any(|m| m == mod_b.local_id) {
196212
// B is above A
197-
return Some(Visibility::Module(mod_b, vis_b));
213+
return Some(Visibility::Module(mod_b, expl_b));
198214
}
199215

200216
if b_ancestors.any(|m| m == mod_a.local_id) {
201217
// A is above B
202-
return Some(Visibility::Module(mod_a, vis_a));
218+
return Some(Visibility::Module(mod_a, expl_a));
203219
}
204220

205221
None
@@ -208,7 +224,8 @@ impl Visibility {
208224
}
209225
}
210226

211-
/// Whether the item was imported through `pub(crate) use` or just `use`.
227+
/// Whether the item was imported through an explicit `pub(crate) use` or just a `use` without
228+
/// visibility.
212229
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
213230
pub enum VisibilityExplicitness {
214231
Explicit,

crates/ide-diagnostics/src/handlers/private_field.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,32 @@ fn main() {
8383
};
8484
strukt.field;
8585
}
86+
"#,
87+
);
88+
}
89+
90+
#[test]
91+
fn block_module_madness2() {
92+
check_diagnostics(
93+
r#"
94+
fn main() {
95+
use crate as ForceParentBlockDefMap;
96+
let strukt = {
97+
use crate as ForceParentBlockDefMap;
98+
{
99+
pub struct Struct {
100+
field: (),
101+
}
102+
{
103+
use crate as ForceParentBlockDefMap;
104+
{
105+
Struct { field: () }
106+
}
107+
}
108+
}
109+
};
110+
strukt.field;
111+
}
86112
"#,
87113
);
88114
}

0 commit comments

Comments
 (0)