Refactor away module.resolve_name()
.
This commit is contained in:
parent
89de52eff0
commit
bfc98f59a4
2 changed files with 75 additions and 77 deletions
|
@ -1250,12 +1250,13 @@ impl<'a> Resolver<'a> {
|
||||||
index: usize,
|
index: usize,
|
||||||
span: Span)
|
span: Span)
|
||||||
-> ResolveResult<Module<'a>> {
|
-> ResolveResult<Module<'a>> {
|
||||||
fn search_parent_externals(needle: Name, module: Module) -> Option<Module> {
|
fn search_parent_externals<'a>(this: &mut Resolver<'a>, needle: Name, module: Module<'a>)
|
||||||
match module.resolve_name(needle, TypeNS, false) {
|
-> Option<Module<'a>> {
|
||||||
|
match this.resolve_name_in_module(module, needle, TypeNS, false, false) {
|
||||||
Success(binding) if binding.is_extern_crate() => Some(module),
|
Success(binding) if binding.is_extern_crate() => Some(module),
|
||||||
_ => match module.parent_link {
|
_ => match module.parent_link {
|
||||||
ModuleParentLink(ref parent, _) => {
|
ModuleParentLink(ref parent, _) => {
|
||||||
search_parent_externals(needle, parent)
|
search_parent_externals(this, needle, parent)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
|
@ -1275,11 +1276,12 @@ impl<'a> Resolver<'a> {
|
||||||
let segment_name = name.as_str();
|
let segment_name = name.as_str();
|
||||||
let module_name = module_to_string(search_module);
|
let module_name = module_to_string(search_module);
|
||||||
let msg = if "???" == &module_name {
|
let msg = if "???" == &module_name {
|
||||||
match search_parent_externals(name, &self.current_module) {
|
let current_module = self.current_module;
|
||||||
|
match search_parent_externals(self, name, current_module) {
|
||||||
Some(module) => {
|
Some(module) => {
|
||||||
let path_str = names_to_string(module_path);
|
let path_str = names_to_string(module_path);
|
||||||
let target_mod_str = module_to_string(&module);
|
let target_mod_str = module_to_string(&module);
|
||||||
let current_mod_str = module_to_string(&self.current_module);
|
let current_mod_str = module_to_string(current_module);
|
||||||
|
|
||||||
let prefix = if target_mod_str == current_mod_str {
|
let prefix = if target_mod_str == current_mod_str {
|
||||||
"self::".to_string()
|
"self::".to_string()
|
||||||
|
@ -1436,8 +1438,8 @@ impl<'a> Resolver<'a> {
|
||||||
if module.def.is_some() {
|
if module.def.is_some() {
|
||||||
return match self.prelude {
|
return match self.prelude {
|
||||||
Some(prelude) if !module.no_implicit_prelude.get() => {
|
Some(prelude) if !module.no_implicit_prelude.get() => {
|
||||||
prelude.resolve_name(name, ns, false).success()
|
self.resolve_name_in_module(prelude, name, ns, false, false).success()
|
||||||
.map(LexicalScopeBinding::Item)
|
.map(LexicalScopeBinding::Item)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
@ -1523,27 +1525,6 @@ impl<'a> Resolver<'a> {
|
||||||
return Success(PrefixFound(containing_module, i));
|
return Success(PrefixFound(containing_module, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to resolve the supplied name in the given module for the
|
|
||||||
/// given namespace. If successful, returns the binding corresponding to
|
|
||||||
/// the name.
|
|
||||||
fn resolve_name_in_module(&mut self,
|
|
||||||
module: Module<'a>,
|
|
||||||
name: Name,
|
|
||||||
namespace: Namespace,
|
|
||||||
use_lexical_scope: bool,
|
|
||||||
record_used: bool)
|
|
||||||
-> ResolveResult<&'a NameBinding<'a>> {
|
|
||||||
debug!("(resolving name in module) resolving `{}` in `{}`", name, module_to_string(module));
|
|
||||||
|
|
||||||
self.populate_module_if_necessary(module);
|
|
||||||
module.resolve_name(name, namespace, use_lexical_scope).and_then(|binding| {
|
|
||||||
if record_used {
|
|
||||||
self.record_use(name, namespace, binding);
|
|
||||||
}
|
|
||||||
Success(binding)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// AST resolution
|
// AST resolution
|
||||||
//
|
//
|
||||||
// We maintain a list of value ribs and type ribs.
|
// We maintain a list of value ribs and type ribs.
|
||||||
|
|
|
@ -133,19 +133,77 @@ impl<'a> NameResolution<'a> {
|
||||||
_ => None, // The binding could be shadowed by a single import, so it is not known.
|
_ => None, // The binding could be shadowed by a single import, so it is not known.
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ::ModuleS<'a> {
|
||||||
|
fn resolution(&self, name: Name, ns: Namespace) -> &'a RefCell<NameResolution<'a>> {
|
||||||
|
*self.resolutions.borrow_mut().entry((name, ns))
|
||||||
|
.or_insert_with(|| self.arenas.alloc_name_resolution())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Resolver<'a> {
|
||||||
|
/// Attempts to resolve the supplied name in the given module for the given namespace.
|
||||||
|
/// If successful, returns the binding corresponding to the name.
|
||||||
|
pub fn resolve_name_in_module(&mut self,
|
||||||
|
module: Module<'a>,
|
||||||
|
name: Name,
|
||||||
|
ns: Namespace,
|
||||||
|
allow_private_imports: bool,
|
||||||
|
record_used: bool)
|
||||||
|
-> ResolveResult<&'a NameBinding<'a>> {
|
||||||
|
self.populate_module_if_necessary(module);
|
||||||
|
|
||||||
|
let resolution = module.resolution(name, ns);
|
||||||
|
let resolution = match resolution.borrow_state() {
|
||||||
|
::std::cell::BorrowState::Unused => resolution.borrow_mut(),
|
||||||
|
_ => return Failed(None), // This happens when there is a cycle of imports
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(result) = self.try_result(&resolution, ns, allow_private_imports) {
|
||||||
|
// If the resolution doesn't depend on glob definability, check privacy and return.
|
||||||
|
return result.and_then(|binding| {
|
||||||
|
if !allow_private_imports && binding.is_import() && !binding.is_pseudo_public() {
|
||||||
|
return Failed(None);
|
||||||
|
}
|
||||||
|
if record_used {
|
||||||
|
self.record_use(name, ns, binding);
|
||||||
|
}
|
||||||
|
Success(binding)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the globs are determined
|
||||||
|
for directive in module.globs.borrow().iter() {
|
||||||
|
if !allow_private_imports && directive.vis != ty::Visibility::Public { continue }
|
||||||
|
if let Some(target_module) = directive.target_module.get() {
|
||||||
|
let result = self.resolve_name_in_module(target_module, name, ns, false, false);
|
||||||
|
if let Indeterminate = result {
|
||||||
|
return Indeterminate;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Indeterminate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Failed(None)
|
||||||
|
}
|
||||||
|
|
||||||
// Returns Some(the resolution of the name), or None if the resolution depends
|
// Returns Some(the resolution of the name), or None if the resolution depends
|
||||||
// on whether more globs can define the name.
|
// on whether more globs can define the name.
|
||||||
fn try_result(&self, ns: Namespace, allow_private_imports: bool)
|
fn try_result(&mut self,
|
||||||
|
resolution: &NameResolution<'a>,
|
||||||
|
ns: Namespace,
|
||||||
|
allow_private_imports: bool)
|
||||||
-> Option<ResolveResult<&'a NameBinding<'a>>> {
|
-> Option<ResolveResult<&'a NameBinding<'a>>> {
|
||||||
match self.binding {
|
match resolution.binding {
|
||||||
Some(binding) if !binding.is_glob_import() =>
|
Some(binding) if !binding.is_glob_import() =>
|
||||||
return Some(Success(binding)),
|
return Some(Success(binding)), // Items and single imports are not shadowable.
|
||||||
_ => {} // Items and single imports are not shadowable
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check if a single import can still define the name.
|
// Check if a single import can still define the name.
|
||||||
match self.single_imports {
|
match resolution.single_imports {
|
||||||
SingleImports::None => {},
|
SingleImports::None => {},
|
||||||
SingleImports::AtLeastOne => return Some(Indeterminate),
|
SingleImports::AtLeastOne => return Some(Indeterminate),
|
||||||
SingleImports::MaybeOne(directive) => {
|
SingleImports::MaybeOne(directive) => {
|
||||||
|
@ -153,7 +211,7 @@ impl<'a> NameResolution<'a> {
|
||||||
// the name, and (3) no public glob has defined the name, the resolution depends
|
// the name, and (3) no public glob has defined the name, the resolution depends
|
||||||
// on whether more globs can define the name.
|
// on whether more globs can define the name.
|
||||||
if !allow_private_imports && directive.vis != ty::Visibility::Public &&
|
if !allow_private_imports && directive.vis != ty::Visibility::Public &&
|
||||||
!self.binding.map(NameBinding::is_pseudo_public).unwrap_or(false) {
|
!resolution.binding.map(NameBinding::is_pseudo_public).unwrap_or(false) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,57 +223,16 @@ impl<'a> NameResolution<'a> {
|
||||||
SingleImport { source, .. } => source,
|
SingleImport { source, .. } => source,
|
||||||
GlobImport { .. } => unreachable!(),
|
GlobImport { .. } => unreachable!(),
|
||||||
};
|
};
|
||||||
match target_module.resolve_name(name, ns, false) {
|
match self.resolve_name_in_module(target_module, name, ns, false, false) {
|
||||||
Failed(_) => {}
|
Failed(_) => {}
|
||||||
_ => return Some(Indeterminate),
|
_ => return Some(Indeterminate),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.binding.map(Success)
|
resolution.binding.map(Success)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ::ModuleS<'a> {
|
|
||||||
fn resolution(&self, name: Name, ns: Namespace) -> &'a RefCell<NameResolution<'a>> {
|
|
||||||
*self.resolutions.borrow_mut().entry((name, ns))
|
|
||||||
.or_insert_with(|| self.arenas.alloc_name_resolution())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_name(&self, name: Name, ns: Namespace, allow_private_imports: bool)
|
|
||||||
-> ResolveResult<&'a NameBinding<'a>> {
|
|
||||||
let resolution = self.resolution(name, ns);
|
|
||||||
let resolution = match resolution.borrow_state() {
|
|
||||||
::std::cell::BorrowState::Unused => resolution.borrow_mut(),
|
|
||||||
_ => return Failed(None), // This happens when there is a cycle of imports
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(result) = resolution.try_result(ns, allow_private_imports) {
|
|
||||||
// If the resolution doesn't depend on glob definability, check privacy and return.
|
|
||||||
return result.and_then(|binding| {
|
|
||||||
let allowed = allow_private_imports || !binding.is_import() ||
|
|
||||||
binding.is_pseudo_public();
|
|
||||||
if allowed { Success(binding) } else { Failed(None) }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the globs are determined
|
|
||||||
for directive in self.globs.borrow().iter() {
|
|
||||||
if !allow_private_imports && directive.vis != ty::Visibility::Public { continue }
|
|
||||||
match directive.target_module.get() {
|
|
||||||
None => return Indeterminate,
|
|
||||||
Some(target_module) => match target_module.resolve_name(name, ns, false) {
|
|
||||||
Indeterminate => return Indeterminate,
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Failed(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Resolver<'a> {
|
|
||||||
// Add an import directive to the current module.
|
// Add an import directive to the current module.
|
||||||
pub fn add_import_directive(&mut self,
|
pub fn add_import_directive(&mut self,
|
||||||
module_path: Vec<Name>,
|
module_path: Vec<Name>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue