Refactor away Target

This commit is contained in:
Jeffrey Seyfried 2016-02-07 21:04:01 +00:00
parent 661b7ce830
commit 7366d105cb
2 changed files with 75 additions and 95 deletions

View File

@ -92,8 +92,7 @@ use std::cell::{Cell, RefCell};
use std::fmt;
use std::mem::replace;
use resolve_imports::{Target, ImportDirective, ImportResolution};
use resolve_imports::Shadowable;
use resolve_imports::{ImportDirective, ImportResolution};
// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
@ -951,6 +950,7 @@ bitflags! {
// Variants are considered `PUBLIC`, but some of them live in private enums.
// We need to track them to prohibit reexports like `pub use PrivEnum::Variant`.
const PRIVATE_VARIANT = 1 << 2,
const PRELUDE = 1 << 3,
}
}
@ -1291,10 +1291,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
name);
return Indeterminate;
}
Success((target, used_proxy)) => {
Success((binding, used_proxy)) => {
// Check to see whether there are type bindings, and, if
// so, whether there is a module within.
if let Some(module_def) = target.binding.module() {
if let Some(module_def) = binding.module() {
search_module = module_def;
// Keep track of the closest private module used
@ -1390,7 +1390,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
debug!("(resolving module path for import) indeterminate; bailing");
return Indeterminate;
}
Success((target, _)) => match target.binding.module() {
Success((binding, _)) => match binding.module() {
Some(containing_module) => {
search_module = containing_module;
start_index = 1;
@ -1424,7 +1424,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
name: Name,
namespace: Namespace,
record_used: bool)
-> ResolveResult<(Target<'a>, bool)> {
-> ResolveResult<(NameBinding<'a>, bool)> {
debug!("(resolving item in lexical scope) resolving `{}` in namespace {:?} in `{}`",
name,
namespace,
@ -1446,10 +1446,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
debug!("(resolving item in lexical scope) indeterminate higher scope; bailing");
return Indeterminate;
}
Success((target, used_reexport)) => {
Success((binding, used_reexport)) => {
// We found the module.
debug!("(resolving item in lexical scope) found name in module, done");
return Success((target, used_reexport));
return Success((binding, used_reexport));
}
}
@ -1543,7 +1543,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
/// Attempts to resolve the supplied name in the given module for the
/// given namespace. If successful, returns the target corresponding to
/// given namespace. If successful, returns the binding corresponding to
/// the name.
///
/// The boolean returned on success is an indicator of whether this lookup
@ -1554,7 +1554,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
namespace: Namespace,
allow_private_imports: bool,
record_used: bool)
-> ResolveResult<(Target<'a>, bool)> {
-> ResolveResult<(NameBinding<'a>, bool)> {
debug!("(resolving name in module) resolving `{}` in `{}`",
name,
module_to_string(&*module_));
@ -1570,7 +1570,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
self.used_crates.insert(krate);
}
}
return Success((Target::new(module_, binding, Shadowable::Never), false));
return Success((binding, false));
}
// Check the list of resolved imports.
@ -1580,12 +1580,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
debug!("(resolving name in module) import unresolved; bailing out");
return Indeterminate;
}
if let Some(target) = import_resolution.target.clone() {
if let Some(binding) = import_resolution.binding.clone() {
debug!("(resolving name in module) resolved to import");
if record_used {
self.record_import_use(name, namespace, &import_resolution);
}
return Success((target, true));
return Success((binding, true));
}
}
Some(..) | None => {} // Continue.
@ -2616,11 +2616,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
-> BareIdentifierPatternResolution {
let module = self.current_module;
match self.resolve_item_in_lexical_scope(module, name, ValueNS, true) {
Success((target, _)) => {
Success((binding, _)) => {
debug!("(resolve bare identifier pattern) succeeded in finding {} at {:?}",
name,
&target.binding);
match target.binding.def() {
&binding);
match binding.def() {
None => {
panic!("resolved name in the value namespace to a set of name bindings \
with no def?!");
@ -2776,7 +2776,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let module = self.current_module;
let name = identifier.unhygienic_name;
match self.resolve_item_in_lexical_scope(module, name, namespace, record_used) {
Success((target, _)) => target.binding.def().map(LocalDef::from_def),
Success((binding, _)) => binding.def().map(LocalDef::from_def),
Failed(Some((span, msg))) => {
resolve_error(self, span, ResolutionError::FailedToResolve(&*msg));
None
@ -2914,7 +2914,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let name = segments.last().unwrap().identifier.name;
let result = self.resolve_name_in_module(containing_module, name, namespace, false, true);
let def = match result {
Success((Target { binding, .. }, _)) => {
Success((binding, _)) => {
let (def, lp) = binding.def_and_lp();
(def, last_private.or(lp))
}
@ -2970,7 +2970,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let name = segments.last().unwrap().identifier.name;
match self.resolve_name_in_module(containing_module, name, namespace, false, true) {
Success((Target { binding, .. }, _)) => {
Success((binding, _)) => {
let (def, lp) = binding.def_and_lp();
Some((def, last_private.or(lp)))
}
@ -3008,12 +3008,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
if let AnonymousModuleRibKind(module) = self.get_ribs(namespace)[i].kind {
if let Success((target, _)) = self.resolve_name_in_module(module,
ident.unhygienic_name,
namespace,
true,
true) {
if let Some(def) = target.binding.def() {
if let Success((binding, _)) = self.resolve_name_in_module(module,
ident.unhygienic_name,
namespace,
true,
true) {
if let Some(def) = binding.def() {
return Some(LocalDef::from_def(def));
}
}
@ -3455,11 +3455,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// Look for imports.
for (&(_, ns), import) in search_module.import_resolutions.borrow().iter() {
if ns != TypeNS { continue }
let target = match import.target {
Some(ref target) => target,
let binding = match import.binding {
Some(ref binding) => binding,
None => continue,
};
let did = match target.binding.def() {
let did = match binding.def() {
Some(Def::Trait(trait_def_id)) => trait_def_id,
Some(..) | None => continue,
};

View File

@ -78,24 +78,14 @@ impl ImportDirective {
shadowable: shadowable,
}
}
}
/// The item that an import resolves to.
#[derive(Clone,Debug)]
pub struct Target<'a> {
pub target_module: Module<'a>,
pub binding: NameBinding<'a>,
pub shadowable: Shadowable,
}
impl<'a> Target<'a> {
pub fn new(target_module: Module<'a>, binding: NameBinding<'a>, shadowable: Shadowable)
-> Self {
Target {
target_module: target_module,
binding: binding,
shadowable: shadowable,
// Given the binding to which this directive resolves in a particular namespace,
// this returns the binding for the name this directive defines in that namespace.
fn import<'a>(&self, mut binding: NameBinding<'a>) -> NameBinding<'a> {
if self.shadowable == Shadowable::Always {
binding.modifiers = binding.modifiers | DefModifiers::PRELUDE;
}
binding
}
}
@ -117,7 +107,7 @@ pub struct ImportResolution<'a> {
pub is_public: bool,
/// Resolution of the name in the namespace
pub target: Option<Target<'a>>,
pub binding: Option<NameBinding<'a>>,
/// The source node of the `use` directive
pub id: NodeId,
@ -128,14 +118,16 @@ impl<'a> ImportResolution<'a> {
ImportResolution {
outstanding_references: 0,
id: id,
target: None,
binding: None,
is_public: is_public,
}
}
pub fn shadowable(&self) -> Shadowable {
match self.target {
Some(ref target) => target.shadowable,
match self.binding {
Some(ref binding) if binding.defined_with(DefModifiers::PRELUDE) =>
Shadowable::Always,
Some(_) => Shadowable::Never,
None => Shadowable::Always,
}
}
@ -217,23 +209,17 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
e.import_directive.is_public)
});
if resolution.target.is_none() {
if resolution.binding.is_none() {
debug!("(resolving import error) adding fake target to import resolution of `{}`",
target);
let name_binding = NameBinding {
let dummy_binding = NameBinding {
modifiers: DefModifiers::IMPORTABLE,
def_or_module: DefOrModule::Def(Def::Err),
span: None,
};
// Create a fake target pointing to a fake name binding in our
// own module
let target = Target::new(e.source_module,
name_binding,
Shadowable::Always);
resolution.target = Some(target);
resolution.binding = Some(dummy_binding);
}
}
@ -374,14 +360,14 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
}
/// Resolves the name in the namespace of the module because it is being imported by
/// importing_module. Returns the module in which the name was defined (as opposed to imported),
/// the name bindings defining the name, and whether or not the name was imported into `module`.
/// importing_module. Returns the name bindings defining the name
/// and whether or not the name was imported.
fn resolve_name_in_module(&mut self,
module: Module<'b>, // Module containing the name
name: Name,
ns: Namespace,
importing_module: Module<'b>) // Module importing the name
-> (ResolveResult<(Module<'b>, NameBinding<'b>)>, bool) {
-> (ResolveResult<NameBinding<'b>>, bool) {
build_reduced_graph::populate_module_if_necessary(self.resolver, module);
if let Some(name_binding) = module.get_child(name, ns) {
if name_binding.is_extern_crate() {
@ -390,7 +376,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
self.resolver.used_crates.insert(krate);
}
}
return (Success((module, name_binding)), false)
return (Success(name_binding), false)
}
// If there is an unresolved glob at this point in the containing module, bail out.
@ -411,10 +397,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
return (Failed(None), false);
}
let target = resolution.target.clone();
if let Some(Target { target_module, binding, shadowable: _ }) = target {
if let Some(binding) = resolution.binding.clone() {
self.resolver.record_import_use(name, ns, &resolution);
(Success((target_module, binding)), true)
(Success(binding), true)
} else {
(Failed(None), false)
}
@ -470,9 +455,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
self.resolve_name_in_module(target_module, source, TypeNS, module_);
match (&value_result, &type_result) {
(&Success((_, ref name_binding)), _) if !value_used_reexport &&
directive.is_public &&
!name_binding.is_public() => {
(&Success(ref name_binding), _) if !value_used_reexport &&
directive.is_public &&
!name_binding.is_public() => {
let msg = format!("`{}` is private, and cannot be reexported", source);
let note_msg = format!("Consider marking `{}` as `pub` in the imported module",
source);
@ -481,8 +466,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
.emit();
}
(_, &Success((_, ref name_binding))) if !type_used_reexport &&
directive.is_public => {
(_, &Success(ref name_binding)) if !type_used_reexport &&
directive.is_public => {
if !name_binding.is_public() {
let msg = format!("`{}` is private, and cannot be reexported", source);
let note_msg =
@ -534,7 +519,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
{
let mut check_and_write_import = |namespace, result, used_public: &mut bool| {
let result: &ResolveResult<(Module<'b>, NameBinding)> = result;
let result: &ResolveResult<NameBinding> = result;
let import_resolution = import_resolutions.get_mut(&(target, namespace)).unwrap();
let namespace_name = match namespace {
@ -543,7 +528,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
};
match *result {
Success((ref target_module, ref name_binding)) => {
Success(ref name_binding) => {
debug!("(resolving single import) found {:?} target: {:?}",
namespace_name,
name_binding.def());
@ -556,9 +541,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
directive.span,
target);
import_resolution.target = Some(Target::new(target_module,
name_binding.clone(),
directive.shadowable));
import_resolution.binding = Some(directive.import(name_binding.clone()));
import_resolution.id = directive.id;
import_resolution.is_public = directive.is_public;
@ -600,8 +583,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
// Record what this import resolves to for later uses in documentation,
// this may resolve to either a value or a type, but for documentation
// purposes it's good enough to just favor one over the other.
import_resolution_value.target.as_ref().map(|target| {
let def = target.binding.def().unwrap();
import_resolution_value.binding.as_ref().map(|binding| {
let def = binding.def().unwrap();
let last_private = if value_used_public { lp } else { DependsOn(def.def_id()) };
(def, last_private)
})
@ -612,8 +595,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
assert!(import_resolution_type.outstanding_references >= 1);
import_resolution_type.outstanding_references -= 1;
import_resolution_type.target.as_ref().map(|target| {
let def = target.binding.def().unwrap();
import_resolution_type.binding.as_ref().map(|binding| {
let def = binding.def().unwrap();
let last_private = if type_used_public { lp } else { DependsOn(def.def_id()) };
(def, last_private)
})
@ -695,15 +678,15 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
import_resolutions.entry((name, ns))
.or_insert_with(|| ImportResolution::new(id, is_public));
match target_import_resolution.target {
Some(ref target) if target_import_resolution.is_public => {
match target_import_resolution.binding {
Some(ref binding) if target_import_resolution.is_public => {
self.check_for_conflicting_import(&dest_import_resolution,
import_directive.span,
name,
ns);
dest_import_resolution.id = id;
dest_import_resolution.is_public = is_public;
dest_import_resolution.target = Some(target.clone());
dest_import_resolution.binding = Some(import_directive.import(binding.clone()));
self.add_export(module_, name, &dest_import_resolution);
}
_ => {}
@ -778,10 +761,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
name);
span_err!(self.resolver.session, import_directive.span, E0251, "{}", msg);
} else {
let target = Target::new(containing_module,
name_binding.clone(),
import_directive.shadowable);
dest_import_resolution.target = Some(target);
dest_import_resolution.binding = Some(import_directive.import(name_binding.clone()));
dest_import_resolution.id = id;
dest_import_resolution.is_public = is_public;
self.add_export(module_, name, &dest_import_resolution);
@ -800,7 +780,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
Some(def_id) => self.resolver.ast_map.as_local_node_id(def_id).unwrap(),
None => return,
};
let export = match resolution.target.as_ref().unwrap().binding.def() {
let export = match resolution.binding.as_ref().unwrap().def() {
Some(def) => Export { name: name, def_id: def.def_id() },
None => return,
};
@ -813,16 +793,16 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
import_span: Span,
name: Name,
namespace: Namespace) {
let target = &import_resolution.target;
let binding = &import_resolution.binding;
debug!("check_for_conflicting_import: {}; target exists: {}",
name,
target.is_some());
binding.is_some());
match *target {
Some(ref target) if target.shadowable != Shadowable::Always => {
match *binding {
Some(ref binding) if !binding.defined_with(DefModifiers::PRELUDE) => {
let ns_word = match namespace {
TypeNS => {
match target.binding.module() {
match binding.module() {
Some(ref module) if module.is_normal() => "module",
Some(ref module) if module.is_trait() => "trait",
_ => "type",
@ -876,8 +856,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
};
if ns == ValueNS {
match import.target {
Some(ref target) if target.shadowable != Shadowable::Always => {
match import.binding {
Some(ref binding) if !binding.defined_with(DefModifiers::PRELUDE) => {
let mut err = struct_span_err!(self.resolver.session,
import_span,
E0255,
@ -892,8 +872,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
Some(_) | None => {}
}
} else {
match import.target {
Some(ref target) if target.shadowable != Shadowable::Always => {
match import.binding {
Some(ref binding) if !binding.defined_with(DefModifiers::PRELUDE) => {
if name_binding.is_extern_crate() {
let msg = format!("import `{0}` conflicts with imported crate \
in this module (maybe you meant `use {0}::*`?)",