]> git.lizzy.rs Git - rust.git/blobdiff - crates/hir_def/src/visibility.rs
parameters.split_last()
[rust.git] / crates / hir_def / src / visibility.rs
index d4b7c9970cea457c4e37d9fee306f384ba2b2442..80009010c52187ddf6f4a533708b8cbacf468024 100644 (file)
@@ -33,17 +33,19 @@ pub(crate) fn from_ast(
         db: &dyn DefDatabase,
         node: InFile<Option<ast::Visibility>>,
     ) -> RawVisibility {
-        Self::from_ast_with_hygiene(node.value, &Hygiene::new(db.upcast(), node.file_id))
+        Self::from_ast_with_hygiene(db, node.value, &Hygiene::new(db.upcast(), node.file_id))
     }
 
     pub(crate) fn from_ast_with_hygiene(
+        db: &dyn DefDatabase,
         node: Option<ast::Visibility>,
         hygiene: &Hygiene,
     ) -> RawVisibility {
-        Self::from_ast_with_hygiene_and_default(node, RawVisibility::private(), hygiene)
+        Self::from_ast_with_hygiene_and_default(db, node, RawVisibility::private(), hygiene)
     }
 
     pub(crate) fn from_ast_with_hygiene_and_default(
+        db: &dyn DefDatabase,
         node: Option<ast::Visibility>,
         default: RawVisibility,
         hygiene: &Hygiene,
@@ -54,7 +56,7 @@ pub(crate) fn from_ast_with_hygiene_and_default(
         };
         match node.kind() {
             ast::VisibilityKind::In(path) => {
-                let path = ModPath::from_src(path, hygiene);
+                let path = ModPath::from_src(db.upcast(), path, hygiene);
                 let path = match path {
                     None => return RawVisibility::private(),
                     Some(path) => path,
@@ -132,8 +134,23 @@ pub(crate) fn is_visible_from_def_map(
         // visibility as the containing module (even though no items are directly nameable from
         // there, getting this right is important for method resolution).
         // In that case, we adjust the visibility of `to_module` to point to the containing module.
-        if to_module.is_block_root(db) {
-            to_module = to_module.containing_module(db).unwrap();
+        // 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.
+        let arc;
+        let to_module_def_map =
+            if to_module.krate == def_map.krate() && to_module.block == def_map.block_id() {
+                cov_mark::hit!(is_visible_from_same_block_def_map);
+                def_map
+            } else {
+                arc = to_module.def_map(db);
+                &arc
+            };
+        let is_block_root = match to_module.block {
+            Some(_) => to_module_def_map[to_module.local_id].parent.is_none(),
+            None => false,
+        };
+        if is_block_root {
+            to_module = to_module_def_map.containing_module(to_module.local_id).unwrap();
         }
 
         // from_module needs to be a descendant of to_module
@@ -170,9 +187,8 @@ pub(crate) fn is_visible_from_def_map(
     /// visible in unrelated modules).
     pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> {
         match (self, other) {
-            (Visibility::Module(_), Visibility::Public)
-            | (Visibility::Public, Visibility::Module(_))
-            | (Visibility::Public, Visibility::Public) => Some(Visibility::Public),
+            (Visibility::Module(_) | Visibility::Public, Visibility::Public)
+            | (Visibility::Public, Visibility::Module(_)) => Some(Visibility::Public),
             (Visibility::Module(mod_a), Visibility::Module(mod_b)) => {
                 if mod_a.krate != mod_b.krate {
                     return None;