Skip to content

Commit 7000e70

Browse files
committed
Replace children and import_resolutions with a single NameResolution-valued map.
Refactor away resolve_name_in_module in resolve_imports.rs Rewrite and improve the core name resolution procedure in NameResolution::result and Module::resolve_name Refactor the duplicate checking code into NameResolution::try_define
1 parent d881eee commit 7000e70

File tree

4 files changed

+224
-502
lines changed

4 files changed

+224
-502
lines changed

src/librustc_resolve/lib.rs

+64-111
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ use rustc_front::hir::{TraitRef, Ty, TyBool, TyChar, TyFloat, TyInt};
8787
use rustc_front::hir::{TyRptr, TyStr, TyUint, TyPath, TyPtr};
8888
use rustc_front::util::walk_pat;
8989

90-
use std::collections::{hash_map, HashMap, HashSet};
90+
use std::collections::{HashMap, HashSet};
9191
use std::cell::{Cell, RefCell};
9292
use std::fmt;
9393
use std::mem::replace;
@@ -342,11 +342,8 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
342342
if let Some(sp) = resolver.ast_map.span_if_local(did) {
343343
err.span_note(sp, "constant defined here");
344344
}
345-
if let Some(directive) = resolver.current_module
346-
.import_resolutions
347-
.borrow()
348-
.get(&(name, ValueNS)) {
349-
if let Some(binding) = directive.binding {
345+
if let Success(binding) = resolver.current_module.resolve_name(name, ValueNS, true) {
346+
if binding.is_import() {
350347
err.span_note(binding.span.unwrap(), "constant imported here");
351348
}
352349
}
@@ -653,10 +650,10 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
653650
}
654651
}
655652

656-
type ErrorMessage = Option<(Span, String)>;
653+
pub type ErrorMessage = Option<(Span, String)>;
657654

658655
#[derive(Clone, PartialEq, Eq)]
659-
enum ResolveResult<T> {
656+
pub enum ResolveResult<T> {
660657
Failed(ErrorMessage), // Failed to resolve the name, optional helpful error message.
661658
Indeterminate, // Couldn't determine due to unresolved globs.
662659
Success(T), // Successfully resolved the import.
@@ -802,7 +799,7 @@ pub struct ModuleS<'a> {
802799
is_public: bool,
803800
is_extern_crate: bool,
804801

805-
children: RefCell<HashMap<(Name, Namespace), &'a NameBinding<'a>>>,
802+
children: RefCell<HashMap<(Name, Namespace), NameResolution<'a>>>,
806803
imports: RefCell<Vec<ImportDirective>>,
807804

808805
// The anonymous children of this node. Anonymous children are pseudo-
@@ -821,9 +818,6 @@ pub struct ModuleS<'a> {
821818
// entry block for `f`.
822819
anonymous_children: RefCell<NodeMap<Module<'a>>>,
823820

824-
// The status of resolving each import in this module.
825-
import_resolutions: RefCell<HashMap<(Name, Namespace), NameResolution<'a>>>,
826-
827821
// The number of unresolved globs that this module exports.
828822
glob_count: Cell<usize>,
829823

@@ -854,7 +848,6 @@ impl<'a> ModuleS<'a> {
854848
children: RefCell::new(HashMap::new()),
855849
imports: RefCell::new(Vec::new()),
856850
anonymous_children: RefCell::new(NodeMap()),
857-
import_resolutions: RefCell::new(HashMap::new()),
858851
glob_count: Cell::new(0),
859852
pub_count: Cell::new(0),
860853
pub_glob_count: Cell::new(0),
@@ -863,39 +856,49 @@ impl<'a> ModuleS<'a> {
863856
}
864857
}
865858

866-
fn get_child(&self, name: Name, ns: Namespace) -> Option<&'a NameBinding<'a>> {
867-
self.children.borrow().get(&(name, ns)).cloned()
859+
fn resolve_name(&self, name: Name, ns: Namespace, allow_private_imports: bool)
860+
-> ResolveResult<&'a NameBinding<'a>> {
861+
let glob_count =
862+
if allow_private_imports { self.glob_count.get() } else { self.pub_glob_count.get() };
863+
864+
self.children.borrow().get(&(name, ns)).cloned().unwrap_or_default().result(glob_count)
865+
.and_then(|binding| {
866+
let allowed = allow_private_imports || !binding.is_import() || binding.is_public();
867+
if allowed { Success(binding) } else { Failed(None) }
868+
})
868869
}
869870

870-
// If the name is not yet defined, define the name and return None.
871-
// Otherwise, return the existing definition.
871+
// Define the name or return the existing binding if there is a collision.
872872
fn try_define_child(&self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>)
873873
-> Result<(), &'a NameBinding<'a>> {
874-
match self.children.borrow_mut().entry((name, ns)) {
875-
hash_map::Entry::Vacant(entry) => { entry.insert(binding); Ok(()) }
876-
hash_map::Entry::Occupied(entry) => { Err(entry.get()) },
877-
}
874+
self.children.borrow_mut().entry((name, ns)).or_insert_with(Default::default)
875+
.try_define(binding)
878876
}
879877

880878
fn increment_outstanding_references_for(&self, name: Name, ns: Namespace) {
881-
let mut resolutions = self.import_resolutions.borrow_mut();
882-
resolutions.entry((name, ns)).or_insert_with(Default::default).outstanding_references += 1;
879+
let mut children = self.children.borrow_mut();
880+
children.entry((name, ns)).or_insert_with(Default::default).outstanding_references += 1;
883881
}
884882

885883
fn decrement_outstanding_references_for(&self, name: Name, ns: Namespace) {
886-
match self.import_resolutions.borrow_mut().get_mut(&(name, ns)).unwrap()
887-
.outstanding_references {
884+
match self.children.borrow_mut().get_mut(&(name, ns)).unwrap().outstanding_references {
888885
0 => panic!("No more outstanding references!"),
889886
ref mut outstanding_references => { *outstanding_references -= 1; }
890887
}
891888
}
892889

890+
fn for_each_child<F: FnMut(Name, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
891+
for (&(name, ns), name_resolution) in self.children.borrow().iter() {
892+
name_resolution.binding.map(|binding| f(name, ns, binding));
893+
}
894+
}
895+
893896
fn for_each_local_child<F: FnMut(Name, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
894-
for (&(name, ns), name_binding) in self.children.borrow().iter() {
895-
if !name_binding.is_extern_crate() {
897+
self.for_each_child(|name, ns, name_binding| {
898+
if !name_binding.is_import() && !name_binding.is_extern_crate() {
896899
f(name, ns, name_binding)
897900
}
898-
}
901+
})
899902
}
900903

901904
fn def_id(&self) -> Option<DefId> {
@@ -1240,7 +1243,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12401243
}
12411244

12421245
#[inline]
1243-
fn record_import_use(&mut self, name: Name, ns: Namespace, binding: &NameBinding<'a>) {
1246+
fn record_use(&mut self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>) {
1247+
// track extern crates for unused_extern_crate lint
1248+
if let Some(DefId { krate, .. }) = binding.module().and_then(ModuleS::def_id) {
1249+
self.used_crates.insert(krate);
1250+
}
1251+
12441252
let import_id = match binding.kind {
12451253
NameBindingKind::Import { id, .. } => id,
12461254
_ => return,
@@ -1278,8 +1286,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
12781286
lp: LastPrivate)
12791287
-> ResolveResult<(Module<'a>, LastPrivate)> {
12801288
fn search_parent_externals<'a>(needle: Name, module: Module<'a>) -> Option<Module<'a>> {
1281-
match module.get_child(needle, TypeNS) {
1282-
Some(binding) if binding.is_extern_crate() => Some(module),
1289+
match module.resolve_name(needle, TypeNS, false) {
1290+
Success(binding) if binding.is_extern_crate() => Some(module),
12831291
_ => match module.parent_link {
12841292
ModuleParentLink(ref parent, _) => {
12851293
search_parent_externals(needle, parent)
@@ -1591,53 +1599,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
15911599
/// given namespace. If successful, returns the binding corresponding to
15921600
/// the name.
15931601
fn resolve_name_in_module(&mut self,
1594-
module_: Module<'a>,
1602+
module: Module<'a>,
15951603
name: Name,
15961604
namespace: Namespace,
15971605
allow_private_imports: bool,
15981606
record_used: bool)
15991607
-> ResolveResult<&'a NameBinding<'a>> {
1600-
debug!("(resolving name in module) resolving `{}` in `{}`",
1601-
name,
1602-
module_to_string(&*module_));
1603-
1604-
// First, check the direct children of the module.
1605-
build_reduced_graph::populate_module_if_necessary(self, module_);
1606-
1607-
if let Some(binding) = module_.get_child(name, namespace) {
1608-
debug!("(resolving name in module) found node as child");
1609-
if binding.is_extern_crate() {
1610-
// track the extern crate as used.
1611-
if let Some(DefId { krate, .. }) = binding.module().unwrap().def_id() {
1612-
self.used_crates.insert(krate);
1613-
}
1614-
}
1615-
return Success(binding);
1616-
}
1617-
1618-
// Check the list of resolved imports.
1619-
match module_.import_resolutions.borrow().get(&(name, namespace)) {
1620-
Some(import_resolution) => {
1621-
if let Some(binding) = import_resolution.binding {
1622-
if !allow_private_imports && binding.is_public() { return Failed(None) }
1623-
if binding.is_public() && import_resolution.outstanding_references != 0 {
1624-
debug!("(resolving name in module) import unresolved; bailing out");
1625-
return Indeterminate;
1626-
}
1608+
debug!("(resolving name in module) resolving `{}` in `{}`", name, module_to_string(module));
16271609

1628-
debug!("(resolving name in module) resolved to import");
1629-
if record_used {
1630-
self.record_import_use(name, namespace, binding);
1631-
}
1632-
return Success(binding);
1633-
}
1610+
build_reduced_graph::populate_module_if_necessary(self, module);
1611+
module.resolve_name(name, namespace, allow_private_imports).and_then(|binding| {
1612+
if record_used {
1613+
self.record_use(name, namespace, binding);
16341614
}
1635-
None => {}
1636-
}
1637-
1638-
// We're out of luck.
1639-
debug!("(resolving name in module) failed to resolve `{}`", name);
1640-
return Failed(None);
1615+
Success(binding)
1616+
})
16411617
}
16421618

16431619
fn report_unresolved_imports(&mut self, module_: Module<'a>) {
@@ -1700,22 +1676,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
17001676
Some(name) => {
17011677
build_reduced_graph::populate_module_if_necessary(self, &orig_module);
17021678

1703-
match orig_module.get_child(name, TypeNS) {
1704-
None => {
1705-
debug!("!!! (with scope) didn't find `{}` in `{}`",
1706-
name,
1707-
module_to_string(&*orig_module));
1708-
}
1709-
Some(name_binding) => {
1710-
match name_binding.module() {
1711-
None => {
1712-
debug!("!!! (with scope) didn't find module for `{}` in `{}`",
1713-
name,
1714-
module_to_string(&*orig_module));
1715-
}
1716-
Some(module_) => {
1717-
self.current_module = module_;
1718-
}
1679+
if let Success(name_binding) = orig_module.resolve_name(name, TypeNS, false) {
1680+
match name_binding.module() {
1681+
None => {
1682+
debug!("!!! (with scope) didn't find module for `{}` in `{}`",
1683+
name,
1684+
module_to_string(orig_module));
1685+
}
1686+
Some(module) => {
1687+
self.current_module = module;
17191688
}
17201689
}
17211690
}
@@ -3101,7 +3070,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
31013070
if name_path.len() == 1 {
31023071
match this.primitive_type_table.primitive_types.get(last_name) {
31033072
Some(_) => None,
3104-
None => this.current_module.get_child(*last_name, TypeNS)
3073+
None => this.current_module.resolve_name(*last_name, TypeNS, true).success()
31053074
.and_then(NameBinding::module)
31063075
}
31073076
} else {
@@ -3161,7 +3130,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
31613130

31623131
// Look for a method in the current self type's impl module.
31633132
if let Some(module) = get_module(self, path.span, &name_path) {
3164-
if let Some(binding) = module.get_child(name, ValueNS) {
3133+
if let Success(binding) = module.resolve_name(name, ValueNS, true) {
31653134
if let Some(Def::Method(did)) = binding.def() {
31663135
if is_static_method(self, did) {
31673136
return StaticMethod(path_names_to_string(&path, 0));
@@ -3484,34 +3453,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
34843453
// Look for trait children.
34853454
build_reduced_graph::populate_module_if_necessary(self, &search_module);
34863455

3487-
for (&(_, ns), name_binding) in search_module.children.borrow().iter() {
3488-
if ns != TypeNS { continue }
3456+
search_module.for_each_child(|_, ns, name_binding| {
3457+
if ns != TypeNS { return }
34893458
let trait_def_id = match name_binding.def() {
34903459
Some(Def::Trait(trait_def_id)) => trait_def_id,
3491-
Some(..) | None => continue,
3460+
Some(..) | None => return,
34923461
};
34933462
if self.trait_item_map.contains_key(&(name, trait_def_id)) {
34943463
add_trait_info(&mut found_traits, trait_def_id, name);
3464+
let trait_name = self.get_trait_name(trait_def_id);
3465+
self.record_use(trait_name, TypeNS, name_binding);
34953466
}
3496-
}
3497-
3498-
// Look for imports.
3499-
for (&(_, ns), import) in search_module.import_resolutions.borrow().iter() {
3500-
if ns != TypeNS { continue }
3501-
let binding = match import.binding {
3502-
Some(binding) => binding,
3503-
None => continue,
3504-
};
3505-
let did = match binding.def() {
3506-
Some(Def::Trait(trait_def_id)) => trait_def_id,
3507-
Some(..) | None => continue,
3508-
};
3509-
if self.trait_item_map.contains_key(&(name, did)) {
3510-
add_trait_info(&mut found_traits, did, name);
3511-
let trait_name = self.get_trait_name(did);
3512-
self.record_import_use(trait_name, TypeNS, binding);
3513-
}
3514-
}
3467+
});
35153468

35163469
match search_module.parent_link {
35173470
NoParentLink | ModuleParentLink(..) => break,

0 commit comments

Comments
 (0)