about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRyo Yoshida <low.ryoshida@gmail.com>2023-02-19 23:30:49 +0900
committerRyo Yoshida <low.ryoshida@gmail.com>2023-02-19 23:55:55 +0900
commit83e24fec98f1fbecb29ea34bfd2bc6e0f32d25aa (patch)
tree24a2799ad8e68c7936a4334805fafa5f619ebc0a
parent443801755c10f64aa3a5b400e8cdc026a7ba6e5e (diff)
downloadrust-83e24fec98f1fbecb29ea34bfd2bc6e0f32d25aa.tar.gz
rust-83e24fec98f1fbecb29ea34bfd2bc6e0f32d25aa.zip
Fix associated item visibility in block-local impls
-rw-r--r--crates/hir-def/src/nameres/collector.rs12
-rw-r--r--crates/hir-def/src/nameres/path_resolution.rs4
-rw-r--r--crates/hir-def/src/resolver.rs4
-rw-r--r--crates/hir-def/src/visibility.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/private_assoc_item.rs38
5 files changed, 52 insertions, 8 deletions
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 4b39a20d86c..e3704bf2164 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -666,8 +666,10 @@ impl DefCollector<'_> {
         macro_: Macro2Id,
         vis: &RawVisibility,
     ) {
-        let vis =
-            self.def_map.resolve_visibility(self.db, module_id, vis).unwrap_or(Visibility::Public);
+        let vis = self
+            .def_map
+            .resolve_visibility(self.db, module_id, vis, false)
+            .unwrap_or(Visibility::Public);
         self.def_map.modules[module_id].scope.declare(macro_.into());
         self.update(
             module_id,
@@ -831,7 +833,7 @@ impl DefCollector<'_> {
         let mut def = directive.status.namespaces();
         let vis = self
             .def_map
-            .resolve_visibility(self.db, module_id, &directive.import.visibility)
+            .resolve_visibility(self.db, module_id, &directive.import.visibility, false)
             .unwrap_or(Visibility::Public);
 
         match import.kind {
@@ -1547,7 +1549,7 @@ impl ModCollector<'_, '_> {
                 };
             let resolve_vis = |def_map: &DefMap, visibility| {
                 def_map
-                    .resolve_visibility(db, self.module_id, visibility)
+                    .resolve_visibility(db, self.module_id, visibility, false)
                     .unwrap_or(Visibility::Public)
             };
 
@@ -1823,7 +1825,7 @@ impl ModCollector<'_, '_> {
     ) -> LocalModuleId {
         let def_map = &mut self.def_collector.def_map;
         let vis = def_map
-            .resolve_visibility(self.def_collector.db, self.module_id, visibility)
+            .resolve_visibility(self.def_collector.db, self.module_id, visibility, false)
             .unwrap_or(Visibility::Public);
         let modules = &mut def_map.modules;
         let origin = match definition {
diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs
index 1d9d5cccded..25478481dd0 100644
--- a/crates/hir-def/src/nameres/path_resolution.rs
+++ b/crates/hir-def/src/nameres/path_resolution.rs
@@ -78,6 +78,7 @@ impl DefMap {
         // pub(path)
         //     ^^^^ this
         visibility: &RawVisibility,
+        within_impl: bool,
     ) -> Option<Visibility> {
         let mut vis = match visibility {
             RawVisibility::Module(path) => {
@@ -102,7 +103,8 @@ impl DefMap {
         // `super` to its parent (etc.). However, visibilities must only refer to a module in the
         // DefMap they're written in, so we restrict them when that happens.
         if let Visibility::Module(m) = vis {
-            if self.block_id() != m.block {
+            // ...unless we're resolving visibility for an associated item in an impl.
+            if self.block_id() != m.block && !within_impl {
                 cov_mark::hit!(adjust_vis_in_block_def_map);
                 vis = Visibility::Module(self.module_id(self.root()));
                 tracing::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis);
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index 86958e3daea..0a44f65ad4a 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -214,10 +214,12 @@ impl Resolver {
         db: &dyn DefDatabase,
         visibility: &RawVisibility,
     ) -> Option<Visibility> {
+        let within_impl =
+            self.scopes().find(|scope| matches!(scope, Scope::ImplDefScope(_))).is_some();
         match visibility {
             RawVisibility::Module(_) => {
                 let (item_map, module) = self.item_scope();
-                item_map.resolve_visibility(db, module, visibility)
+                item_map.resolve_visibility(db, module, visibility, within_impl)
             }
             RawVisibility::Public => Some(Visibility::Public),
         }
diff --git a/crates/hir-def/src/visibility.rs b/crates/hir-def/src/visibility.rs
index eee73b9f373..c9fcaae56cf 100644
--- a/crates/hir-def/src/visibility.rs
+++ b/crates/hir-def/src/visibility.rs
@@ -120,7 +120,7 @@ impl Visibility {
         self,
         db: &dyn DefDatabase,
         def_map: &DefMap,
-        mut from_module: crate::LocalModuleId,
+        mut from_module: LocalModuleId,
     ) -> bool {
         let mut to_module = match self {
             Visibility::Module(m) => m,
diff --git a/crates/ide-diagnostics/src/handlers/private_assoc_item.rs b/crates/ide-diagnostics/src/handlers/private_assoc_item.rs
index 0b3121c765d..67da5c7f27d 100644
--- a/crates/ide-diagnostics/src/handlers/private_assoc_item.rs
+++ b/crates/ide-diagnostics/src/handlers/private_assoc_item.rs
@@ -118,4 +118,42 @@ fn main(s: module::Struct) {
 "#,
         );
     }
+
+    #[test]
+    fn can_see_through_top_level_anonymous_const() {
+        // regression test for #14046.
+        check_diagnostics(
+            r#"
+struct S;
+mod m {
+    const _: () = {
+        impl crate::S {
+            pub(crate) fn method(self) {}
+            pub(crate) const A: usize = 42;
+        }
+    };
+    mod inner {
+        const _: () = {
+            impl crate::S {
+                pub(crate) fn method2(self) {}
+                pub(crate) const B: usize = 42;
+                pub(super) fn private(self) {}
+                pub(super) const PRIVATE: usize = 42;
+            }
+        };
+    }
+}
+fn main() {
+    S.method();
+    S::A;
+    S.method2();
+    S::B;
+    S.private();
+  //^^^^^^^^^^^ error: function `private` is private
+    S::PRIVATE;
+  //^^^^^^^^^^ error: const `PRIVATE` is private
+}
+"#,
+        );
+    }
 }