Skip to content

Commit 672a3d9

Browse files
committed
Auto merge of #30294 - jseyfried:fix_shadowed_use_visibility, r=nrc
This fixes a bug in which the visibility of a use declaration defining a name in one namespace (e.g. the value namespace) is overridden by a later use declaration defining the same name in the other namespace (e.g. the type namespace). For example, ```rust fn f() {} pub mod bar {} mod foo { use f; // This import should not be visible outside `foo`, pub use bar as f; // but it visible outside of `foo` because of this import. } fn main() { foo::f(); } ``` As the example demonstrates, this is a [breaking-change], but it looks unlikely to cause breakage in practice, and any breakage can be fixed by correcting visibility modifiers.
2 parents ae5d095 + ada87fa commit 672a3d9

File tree

6 files changed

+168
-163
lines changed

6 files changed

+168
-163
lines changed

src/librustc_resolve/build_reduced_graph.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
use DefModifiers;
1717
use resolve_imports::ImportDirective;
1818
use resolve_imports::ImportDirectiveSubclass::{self, SingleImport, GlobImport};
19-
use resolve_imports::ImportResolution;
19+
use resolve_imports::{ImportResolution, ImportResolutionPerNamespace};
2020
use Module;
2121
use Namespace::{TypeNS, ValueNS};
2222
use NameBindings;
@@ -822,22 +822,23 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
822822

823823
let mut import_resolutions = module_.import_resolutions.borrow_mut();
824824
match import_resolutions.get_mut(&target) {
825-
Some(resolution) => {
825+
Some(resolution_per_ns) => {
826826
debug!("(building import directive) bumping reference");
827-
resolution.outstanding_references += 1;
827+
resolution_per_ns.outstanding_references += 1;
828828

829829
// the source of this name is different now
830-
resolution.type_id = id;
831-
resolution.value_id = id;
832-
resolution.is_public = is_public;
830+
let resolution =
831+
ImportResolution { id: id, is_public: is_public, target: None };
832+
resolution_per_ns[TypeNS] = resolution.clone();
833+
resolution_per_ns[ValueNS] = resolution;
833834
return;
834835
}
835836
None => {}
836837
}
837838
debug!("(building import directive) creating new");
838-
let mut resolution = ImportResolution::new(id, is_public);
839-
resolution.outstanding_references = 1;
840-
import_resolutions.insert(target, resolution);
839+
let mut import_resolution_per_ns = ImportResolutionPerNamespace::new(id, is_public);
840+
import_resolution_per_ns.outstanding_references = 1;
841+
import_resolutions.insert(target, import_resolution_per_ns);
841842
}
842843
GlobImport => {
843844
// Set the glob flag. This tells us that we don't know the

src/librustc_resolve/lib.rs

+17-15
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ use std::mem::replace;
9696
use std::rc::{Rc, Weak};
9797
use std::usize;
9898

99-
use resolve_imports::{Target, ImportDirective, ImportResolution};
99+
use resolve_imports::{Target, ImportDirective, ImportResolutionPerNamespace};
100100
use resolve_imports::Shadowable;
101101

102102
// NB: This module needs to be declared first so diagnostics are
@@ -328,7 +328,7 @@ fn resolve_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
328328
.import_resolutions
329329
.borrow()
330330
.get(&name) {
331-
let item = resolver.ast_map.expect_item(directive.value_id);
331+
let item = resolver.ast_map.expect_item(directive.value_ns.id);
332332
resolver.session.span_note(item.span, "constant imported here");
333333
}
334334
}
@@ -793,7 +793,7 @@ pub struct Module {
793793
anonymous_children: RefCell<NodeMap<Rc<Module>>>,
794794

795795
// The status of resolving each import in this module.
796-
import_resolutions: RefCell<HashMap<Name, ImportResolution>>,
796+
import_resolutions: RefCell<HashMap<Name, ImportResolutionPerNamespace>>,
797797

798798
// The number of unresolved globs that this module exports.
799799
glob_count: Cell<usize>,
@@ -912,7 +912,7 @@ bitflags! {
912912
// Records a possibly-private value, type, or module definition.
913913
#[derive(Debug)]
914914
struct NsDef {
915-
modifiers: DefModifiers, // see note in ImportResolution about how to use this
915+
modifiers: DefModifiers, // see note in ImportResolutionPerNamespace about how to use this
916916
def_or_module: DefOrModule,
917917
span: Option<Span>,
918918
}
@@ -1491,7 +1491,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
14911491
// adjacent import statements are processed as though they mutated the
14921492
// current scope.
14931493
if let Some(import_resolution) = module_.import_resolutions.borrow().get(&name) {
1494-
match (*import_resolution).target_for_namespace(namespace) {
1494+
match import_resolution[namespace].target.clone() {
14951495
None => {
14961496
// Not found; continue.
14971497
debug!("(resolving item in lexical scope) found import resolution, but not \
@@ -1501,7 +1501,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
15011501
Some(target) => {
15021502
debug!("(resolving item in lexical scope) using import resolution");
15031503
// track used imports and extern crates as well
1504-
let id = import_resolution.id(namespace);
1504+
let id = import_resolution[namespace].id;
15051505
self.used_imports.insert((id, namespace));
15061506
self.record_import_use(id, name);
15071507
if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
@@ -1712,21 +1712,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
17121712

17131713
// Check the list of resolved imports.
17141714
match module_.import_resolutions.borrow().get(&name) {
1715-
Some(import_resolution) if allow_private_imports || import_resolution.is_public => {
1715+
Some(import_resolution) if allow_private_imports ||
1716+
import_resolution[namespace].is_public => {
17161717

1717-
if import_resolution.is_public && import_resolution.outstanding_references != 0 {
1718+
if import_resolution[namespace].is_public &&
1719+
import_resolution.outstanding_references != 0 {
17181720
debug!("(resolving name in module) import unresolved; bailing out");
17191721
return Indeterminate;
17201722
}
1721-
match import_resolution.target_for_namespace(namespace) {
1723+
match import_resolution[namespace].target.clone() {
17221724
None => {
17231725
debug!("(resolving name in module) name found, but not in namespace {:?}",
17241726
namespace);
17251727
}
17261728
Some(target) => {
17271729
debug!("(resolving name in module) resolved to import");
17281730
// track used imports and extern crates as well
1729-
let id = import_resolution.id(namespace);
1731+
let id = import_resolution[namespace].id;
17301732
self.used_imports.insert((id, namespace));
17311733
self.record_import_use(id, name);
17321734
if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
@@ -3651,17 +3653,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
36513653

36523654
// Look for imports.
36533655
for (_, import) in search_module.import_resolutions.borrow().iter() {
3654-
let target = match import.target_for_namespace(TypeNS) {
3656+
let target = match import.type_ns.target {
36553657
None => continue,
3656-
Some(target) => target,
3658+
Some(ref target) => target,
36573659
};
36583660
let did = match target.binding.def() {
36593661
Some(DefTrait(trait_def_id)) => trait_def_id,
36603662
Some(..) | None => continue,
36613663
};
36623664
if self.trait_item_map.contains_key(&(name, did)) {
36633665
add_trait_info(&mut found_traits, did, name);
3664-
let id = import.type_id;
3666+
let id = import.type_ns.id;
36653667
self.used_imports.insert((id, TypeNS));
36663668
let trait_name = self.get_trait_name(did);
36673669
self.record_import_use(id, trait_name);
@@ -3734,7 +3736,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
37343736
let import_resolutions = module_.import_resolutions.borrow();
37353737
for (&name, import_resolution) in import_resolutions.iter() {
37363738
let value_repr;
3737-
match import_resolution.target_for_namespace(ValueNS) {
3739+
match import_resolution.value_ns.target {
37383740
None => {
37393741
value_repr = "".to_string();
37403742
}
@@ -3745,7 +3747,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
37453747
}
37463748

37473749
let type_repr;
3748-
match import_resolution.target_for_namespace(TypeNS) {
3750+
match import_resolution.type_ns.target {
37493751
None => {
37503752
type_repr = "".to_string();
37513753
}

src/librustc_resolve/record_exports.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -130,13 +130,14 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
130130

131131
fn add_exports_for_module(&mut self, exports: &mut Vec<Export>, module_: &Module) {
132132
for (name, import_resolution) in module_.import_resolutions.borrow().iter() {
133-
if !import_resolution.is_public {
134-
continue;
135-
}
136133
let xs = [TypeNS, ValueNS];
137134
for &ns in &xs {
138-
match import_resolution.target_for_namespace(ns) {
139-
Some(target) => {
135+
if !import_resolution[ns].is_public {
136+
continue;
137+
}
138+
139+
match import_resolution[ns].target {
140+
Some(ref target) => {
140141
debug!("(computing exports) maybe export '{}'", name);
141142
self.add_export_of_namebinding(exports, *name, &target.binding)
142143
}

0 commit comments

Comments
 (0)