Cleanup visibility.rs
This commit is contained in:
parent
dc69255b83
commit
36fb1409ed
@ -658,7 +658,7 @@ fn lower_type_bounds(&mut self, node: &dyn ast::HasTypeBounds) -> Box<[Interned<
|
|||||||
|
|
||||||
fn lower_visibility(&mut self, item: &dyn ast::HasVisibility) -> RawVisibilityId {
|
fn lower_visibility(&mut self, item: &dyn ast::HasVisibility) -> RawVisibilityId {
|
||||||
let vis =
|
let vis =
|
||||||
RawVisibility::from_ast_with_span_map(self.db, item.visibility(), self.span_map());
|
RawVisibility::from_opt_ast_with_span_map(self.db, item.visibility(), self.span_map());
|
||||||
self.data().vis.alloc(vis)
|
self.data().vis.alloc(vis)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,6 +248,7 @@ pub fn resolve_visibility(
|
|||||||
RawVisibility::Public => Some(Visibility::Public),
|
RawVisibility::Public => Some(Visibility::Public),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_path_in_value_ns(
|
pub fn resolve_path_in_value_ns(
|
||||||
&self,
|
&self,
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
|
@ -37,10 +37,14 @@ pub(crate) fn from_ast(
|
|||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
node: InFile<Option<ast::Visibility>>,
|
node: InFile<Option<ast::Visibility>>,
|
||||||
) -> RawVisibility {
|
) -> RawVisibility {
|
||||||
|
let node = match node.transpose() {
|
||||||
|
None => return RawVisibility::private(),
|
||||||
|
Some(node) => node,
|
||||||
|
};
|
||||||
Self::from_ast_with_span_map(db, node.value, db.span_map(node.file_id).as_ref())
|
Self::from_ast_with_span_map(db, node.value, db.span_map(node.file_id).as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_ast_with_span_map(
|
pub(crate) fn from_opt_ast_with_span_map(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
node: Option<ast::Visibility>,
|
node: Option<ast::Visibility>,
|
||||||
span_map: SpanMapRef<'_>,
|
span_map: SpanMapRef<'_>,
|
||||||
@ -49,29 +53,28 @@ pub(crate) fn from_ast_with_span_map(
|
|||||||
None => return RawVisibility::private(),
|
None => return RawVisibility::private(),
|
||||||
Some(node) => node,
|
Some(node) => node,
|
||||||
};
|
};
|
||||||
match node.kind() {
|
Self::from_ast_with_span_map(db, node, span_map)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_ast_with_span_map(
|
||||||
|
db: &dyn DefDatabase,
|
||||||
|
node: ast::Visibility,
|
||||||
|
span_map: SpanMapRef<'_>,
|
||||||
|
) -> RawVisibility {
|
||||||
|
let path = match node.kind() {
|
||||||
ast::VisibilityKind::In(path) => {
|
ast::VisibilityKind::In(path) => {
|
||||||
let path = ModPath::from_src(db.upcast(), path, span_map);
|
let path = ModPath::from_src(db.upcast(), path, span_map);
|
||||||
let path = match path {
|
match path {
|
||||||
None => return RawVisibility::private(),
|
None => return RawVisibility::private(),
|
||||||
Some(path) => path,
|
Some(path) => path,
|
||||||
};
|
}
|
||||||
RawVisibility::Module(path, VisibilityExplicitness::Explicit)
|
|
||||||
}
|
}
|
||||||
ast::VisibilityKind::PubCrate => {
|
ast::VisibilityKind::PubCrate => ModPath::from_kind(PathKind::Crate),
|
||||||
let path = ModPath::from_kind(PathKind::Crate);
|
ast::VisibilityKind::PubSuper => ModPath::from_kind(PathKind::Super(1)),
|
||||||
RawVisibility::Module(path, VisibilityExplicitness::Explicit)
|
ast::VisibilityKind::PubSelf => ModPath::from_kind(PathKind::Super(0)),
|
||||||
}
|
ast::VisibilityKind::Pub => return RawVisibility::Public,
|
||||||
ast::VisibilityKind::PubSuper => {
|
};
|
||||||
let path = ModPath::from_kind(PathKind::Super(1));
|
RawVisibility::Module(path, VisibilityExplicitness::Explicit)
|
||||||
RawVisibility::Module(path, VisibilityExplicitness::Explicit)
|
|
||||||
}
|
|
||||||
ast::VisibilityKind::PubSelf => {
|
|
||||||
let path = ModPath::from_kind(PathKind::Super(0));
|
|
||||||
RawVisibility::Module(path, VisibilityExplicitness::Explicit)
|
|
||||||
}
|
|
||||||
ast::VisibilityKind::Pub => RawVisibility::Public,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve(
|
pub fn resolve(
|
||||||
@ -94,6 +97,10 @@ pub enum Visibility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Visibility {
|
impl Visibility {
|
||||||
|
pub(crate) fn is_visible_from_other_crate(self) -> bool {
|
||||||
|
matches!(self, Visibility::Public)
|
||||||
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
pub fn is_visible_from(self, db: &dyn DefDatabase, from_module: ModuleId) -> bool {
|
pub fn is_visible_from(self, db: &dyn DefDatabase, from_module: ModuleId) -> bool {
|
||||||
let to_module = match self {
|
let to_module = match self {
|
||||||
@ -105,24 +112,33 @@ pub fn is_visible_from(self, db: &dyn DefDatabase, from_module: ModuleId) -> boo
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let def_map = from_module.def_map(db);
|
let def_map = from_module.def_map(db);
|
||||||
self.is_visible_from_def_map(db, &def_map, from_module.local_id)
|
Self::is_visible_from_def_map_(db, &def_map, to_module, from_module.local_id)
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn is_visible_from_other_crate(self) -> bool {
|
|
||||||
matches!(self, Visibility::Public)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_visible_from_def_map(
|
pub(crate) fn is_visible_from_def_map(
|
||||||
self,
|
self,
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
def_map: &DefMap,
|
def_map: &DefMap,
|
||||||
mut from_module: LocalModuleId,
|
from_module: LocalModuleId,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut to_module = match self {
|
let to_module = match self {
|
||||||
Visibility::Module(m, _) => m,
|
Visibility::Module(m, _) => m,
|
||||||
Visibility::Public => return true,
|
Visibility::Public => return true,
|
||||||
};
|
};
|
||||||
|
// if they're not in the same crate, it can't be visible
|
||||||
|
if def_map.krate() != to_module.krate {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Self::is_visible_from_def_map_(db, def_map, to_module, from_module)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_visible_from_def_map_(
|
||||||
|
db: &dyn DefDatabase,
|
||||||
|
def_map: &DefMap,
|
||||||
|
mut to_module: ModuleId,
|
||||||
|
mut from_module: LocalModuleId,
|
||||||
|
) -> bool {
|
||||||
|
debug_assert_eq!(to_module.krate, def_map.krate());
|
||||||
// `to_module` might be the root module of a block expression. Those have the same
|
// `to_module` might be the root module of a block expression. Those have the same
|
||||||
// visibility as the containing module (even though no items are directly nameable from
|
// visibility as the containing module (even though no items are directly nameable from
|
||||||
// there, getting this right is important for method resolution).
|
// there, getting this right is important for method resolution).
|
||||||
@ -130,20 +146,25 @@ pub(crate) fn is_visible_from_def_map(
|
|||||||
|
|
||||||
// Additional complication: `to_module` might be in `from_module`'s `DefMap`, which we're
|
// Additional complication: `to_module` might be in `from_module`'s `DefMap`, which we're
|
||||||
// currently computing, so we must not call the `def_map` query for it.
|
// currently computing, so we must not call the `def_map` query for it.
|
||||||
let mut arc;
|
let def_map_block = def_map.block_id();
|
||||||
loop {
|
loop {
|
||||||
let to_module_def_map =
|
match (to_module.block, def_map_block) {
|
||||||
if to_module.krate == def_map.krate() && to_module.block == def_map.block_id() {
|
// to_module is not a block, so there is no parent def map to use
|
||||||
|
(None, _) => (),
|
||||||
|
(Some(a), Some(b)) if a == b => {
|
||||||
cov_mark::hit!(is_visible_from_same_block_def_map);
|
cov_mark::hit!(is_visible_from_same_block_def_map);
|
||||||
def_map
|
if let Some(parent) = def_map.parent() {
|
||||||
} else {
|
to_module = parent;
|
||||||
arc = to_module.def_map(db);
|
}
|
||||||
&arc
|
}
|
||||||
};
|
_ => {
|
||||||
match to_module_def_map.parent() {
|
if let Some(parent) = to_module.def_map(db).parent() {
|
||||||
Some(parent) => to_module = parent,
|
to_module = parent;
|
||||||
None => break,
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// from_module needs to be a descendant of to_module
|
// from_module needs to be a descendant of to_module
|
||||||
@ -176,30 +197,25 @@ pub(crate) fn is_visible_from_def_map(
|
|||||||
/// visible in unrelated modules).
|
/// visible in unrelated modules).
|
||||||
pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> {
|
pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Visibility::Module(_, _) | Visibility::Public, Visibility::Public)
|
(_, Visibility::Public) | (Visibility::Public, _) => Some(Visibility::Public),
|
||||||
| (Visibility::Public, Visibility::Module(_, _)) => Some(Visibility::Public),
|
(Visibility::Module(mod_a, expl_a), Visibility::Module(mod_b, expl_b)) => {
|
||||||
(Visibility::Module(mod_a, vis_a), Visibility::Module(mod_b, vis_b)) => {
|
|
||||||
if mod_a.krate != mod_b.krate {
|
if mod_a.krate != mod_b.krate {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut a_ancestors = iter::successors(Some(mod_a.local_id), |&m| {
|
let mut a_ancestors =
|
||||||
let parent_id = def_map[m].parent?;
|
iter::successors(Some(mod_a.local_id), |&m| def_map[m].parent);
|
||||||
Some(parent_id)
|
let mut b_ancestors =
|
||||||
});
|
iter::successors(Some(mod_b.local_id), |&m| def_map[m].parent);
|
||||||
let mut b_ancestors = iter::successors(Some(mod_b.local_id), |&m| {
|
|
||||||
let parent_id = def_map[m].parent?;
|
|
||||||
Some(parent_id)
|
|
||||||
});
|
|
||||||
|
|
||||||
if a_ancestors.any(|m| m == mod_b.local_id) {
|
if a_ancestors.any(|m| m == mod_b.local_id) {
|
||||||
// B is above A
|
// B is above A
|
||||||
return Some(Visibility::Module(mod_b, vis_b));
|
return Some(Visibility::Module(mod_b, expl_b));
|
||||||
}
|
}
|
||||||
|
|
||||||
if b_ancestors.any(|m| m == mod_a.local_id) {
|
if b_ancestors.any(|m| m == mod_a.local_id) {
|
||||||
// A is above B
|
// A is above B
|
||||||
return Some(Visibility::Module(mod_a, vis_a));
|
return Some(Visibility::Module(mod_a, expl_a));
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
@ -208,7 +224,8 @@ pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibilit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the item was imported through `pub(crate) use` or just `use`.
|
/// Whether the item was imported through an explicit `pub(crate) use` or just a `use` without
|
||||||
|
/// visibility.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum VisibilityExplicitness {
|
pub enum VisibilityExplicitness {
|
||||||
Explicit,
|
Explicit,
|
||||||
|
@ -83,6 +83,32 @@ pub struct Struct {
|
|||||||
};
|
};
|
||||||
strukt.field;
|
strukt.field;
|
||||||
}
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn block_module_madness2() {
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
fn main() {
|
||||||
|
use crate as ForceParentBlockDefMap;
|
||||||
|
let strukt = {
|
||||||
|
use crate as ForceParentBlockDefMap;
|
||||||
|
{
|
||||||
|
pub struct Struct {
|
||||||
|
field: (),
|
||||||
|
}
|
||||||
|
{
|
||||||
|
use crate as ForceParentBlockDefMap;
|
||||||
|
{
|
||||||
|
Struct { field: () }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
strukt.field;
|
||||||
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user