Skip to content

Commit 4ddff03

Browse files
committed
resolve: Set effective visibilities for imports more precisely
Instead of setting them for all primary and additional IDs of the import, only set them for the binding's true ID.
1 parent 5be901a commit 4ddff03

File tree

4 files changed

+32
-12
lines changed

4 files changed

+32
-12
lines changed

compiler/rustc_resolve/src/access_levels.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use crate::imports::ImportKind;
21
use crate::NameBinding;
32
use crate::NameBindingKind;
43
use crate::Resolver;
@@ -54,15 +53,11 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
5453
// sets the rest of the `use` chain to `AccessLevel::Exported` until
5554
// we hit the actual exported item.
5655
let set_import_binding_access_level =
57-
|this: &mut Self, mut binding: &NameBinding<'a>, mut access_level| {
56+
|this: &mut Self, mut binding: &NameBinding<'a>, mut access_level, ns| {
5857
while let NameBindingKind::Import { binding: nested_binding, import, .. } =
5958
binding.kind
6059
{
61-
this.set_access_level(import.id, access_level);
62-
if let ImportKind::Single { additional_ids, .. } = import.kind {
63-
this.set_access_level(additional_ids.0, access_level);
64-
this.set_access_level(additional_ids.1, access_level);
65-
}
60+
this.set_access_level(this.r.import_id_for_ns(import, ns), access_level);
6661

6762
access_level = Some(AccessLevel::Exported);
6863
binding = nested_binding;
@@ -72,11 +67,11 @@ impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
7267
let module = self.r.get_module(module_id.to_def_id()).unwrap();
7368
let resolutions = self.r.resolutions(module);
7469

75-
for (.., name_resolution) in resolutions.borrow().iter() {
70+
for (key, name_resolution) in resolutions.borrow().iter() {
7671
if let Some(binding) = name_resolution.borrow().binding() && binding.vis.is_public() && !binding.is_ambiguity() {
7772
let access_level = match binding.is_import() {
7873
true => {
79-
set_import_binding_access_level(self, binding, module_level);
74+
set_import_binding_access_level(self, binding, module_level, key.ns);
8075
Some(AccessLevel::Exported)
8176
},
8277
false => module_level,

compiler/rustc_resolve/src/imports.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::diagnostics::Suggestion;
44
use crate::Determinacy::{self, *};
5-
use crate::Namespace::{MacroNS, TypeNS};
5+
use crate::Namespace::{self, *};
66
use crate::{module_to_string, names_to_string};
77
use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment};
88
use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet};
@@ -371,6 +371,31 @@ impl<'a> Resolver<'a> {
371371
self.used_imports.insert(import.id);
372372
}
373373
}
374+
375+
/// Take primary and additional node IDs from an import and select one that corresponds to the
376+
/// given namespace. The logic must match the corresponding logic from `fn lower_use_tree` that
377+
/// assigns resolutons to IDs.
378+
pub(crate) fn import_id_for_ns(&self, import: &Import<'_>, ns: Namespace) -> NodeId {
379+
if let ImportKind::Single { additional_ids: (id1, id2), .. } = import.kind {
380+
if let Some(resolutions) = self.import_res_map.get(&import.id) {
381+
assert!(resolutions[ns].is_some(), "incorrectly finalized import");
382+
return match ns {
383+
TypeNS => import.id,
384+
ValueNS => match resolutions.type_ns {
385+
Some(_) => id1,
386+
None => import.id,
387+
},
388+
MacroNS => match (resolutions.type_ns, resolutions.value_ns) {
389+
(Some(_), Some(_)) => id2,
390+
(Some(_), None) | (None, Some(_)) => id1,
391+
(None, None) => import.id,
392+
},
393+
};
394+
}
395+
}
396+
397+
import.id
398+
}
374399
}
375400

376401
/// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved

src/test/ui/privacy/access_levels.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,6 @@ mod half_public_import {
7070

7171
#[rustc_effective_visibility]
7272
pub use half_public_import::HalfPublicImport; //~ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
73-
//~^ ERROR Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
73+
//~^ ERROR Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self)
7474

7575
fn main() {}

src/test/ui/privacy/access_levels.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
112112
LL | pub use half_public_import::HalfPublicImport;
113113
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
114114

115-
error: Public: pub, Exported: pub, Reachable: pub, ReachableFromImplTrait: pub
115+
error: Public: pub(self), Exported: pub(self), Reachable: pub(self), ReachableFromImplTrait: pub(self)
116116
--> $DIR/access_levels.rs:72:9
117117
|
118118
LL | pub use half_public_import::HalfPublicImport;

0 commit comments

Comments
 (0)