about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs31
-rw-r--r--src/librustc_resolve/lib.rs308
-rw-r--r--src/librustc_resolve/resolve_imports.rs709
-rw-r--r--src/test/compile-fail/double-type-import.rs2
-rw-r--r--src/test/compile-fail/unresolved-import.rs4
5 files changed, 377 insertions, 677 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 6bc73194aa9..775ed34ab07 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -16,10 +16,9 @@
 use DefModifiers;
 use resolve_imports::ImportDirective;
 use resolve_imports::ImportDirectiveSubclass::{self, SingleImport, GlobImport};
-use resolve_imports::ImportResolution;
 use Module;
 use Namespace::{self, TypeNS, ValueNS};
-use {NameBinding, DefOrModule};
+use {NameBinding, NameBindingKind};
 use {names_to_string, module_to_string};
 use ParentLink::{ModuleParentLink, BlockParentLink};
 use Resolver;
@@ -82,8 +81,8 @@ impl<'a> ToNameBinding<'a> for (Module<'a>, Span) {
 
 impl<'a> ToNameBinding<'a> for (Def, Span, DefModifiers) {
     fn to_name_binding(self) -> NameBinding<'a> {
-        let def = DefOrModule::Def(self.0);
-        NameBinding { modifiers: self.2, def_or_module: def, span: Some(self.1) }
+        let kind = NameBindingKind::Def(self.0);
+        NameBinding { modifiers: self.2, kind: kind, span: Some(self.1) }
     }
 }
 
@@ -101,16 +100,16 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
     fn try_define<T>(&self, parent: Module<'b>, name: Name, ns: Namespace, def: T)
         where T: ToNameBinding<'b>
     {
-        parent.try_define_child(name, ns, def.to_name_binding());
+        let _ = parent.try_define_child(name, ns, self.new_name_binding(def.to_name_binding()));
     }
 
     /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
     /// otherwise, reports an error.
     fn define<T: ToNameBinding<'b>>(&self, parent: Module<'b>, name: Name, ns: Namespace, def: T) {
-        let binding = def.to_name_binding();
-        let old_binding = match parent.try_define_child(name, ns, binding.clone()) {
-            Some(old_binding) => old_binding,
-            None => return,
+        let binding = self.new_name_binding(def.to_name_binding());
+        let old_binding = match parent.try_define_child(name, ns, binding) {
+            Ok(()) => return,
+            Err(old_binding) => old_binding,
         };
 
         let span = binding.span.unwrap_or(DUMMY_SP);
@@ -699,18 +698,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                 debug!("(building import directive) building import directive: {}::{}",
                        names_to_string(&module_.imports.borrow().last().unwrap().module_path),
                        target);
-
-                let mut import_resolutions = module_.import_resolutions.borrow_mut();
-                for &ns in [TypeNS, ValueNS].iter() {
-                    let mut resolution = import_resolutions.entry((target, ns)).or_insert(
-                        ImportResolution::new(id, is_public)
-                    );
-
-                    resolution.outstanding_references += 1;
-                    // the source of this name is different now
-                    resolution.id = id;
-                    resolution.is_public = is_public;
-                }
+                module_.increment_outstanding_references_for(target, ValueNS);
+                module_.increment_outstanding_references_for(target, TypeNS);
             }
             GlobImport => {
                 // Set the glob flag. This tells us that we don't know the
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 054aa1d5f55..5fbe06a868f 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -87,13 +87,12 @@ use rustc_front::hir::{TraitRef, Ty, TyBool, TyChar, TyFloat, TyInt};
 use rustc_front::hir::{TyRptr, TyStr, TyUint, TyPath, TyPtr};
 use rustc_front::util::walk_pat;
 
-use std::collections::{hash_map, HashMap, HashSet};
+use std::collections::{HashMap, HashSet};
 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, NameResolution};
 
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
@@ -343,12 +342,10 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
             if let Some(sp) = resolver.ast_map.span_if_local(did) {
                 err.span_note(sp, "constant defined here");
             }
-            if let Some(directive) = resolver.current_module
-                                             .import_resolutions
-                                             .borrow()
-                                             .get(&(name, ValueNS)) {
-                let item = resolver.ast_map.expect_item(directive.id);
-                err.span_note(item.span, "constant imported here");
+            if let Success(binding) = resolver.current_module.resolve_name(name, ValueNS, true) {
+                if binding.is_import() {
+                    err.span_note(binding.span.unwrap(), "constant imported here");
+                }
             }
             err
         }
@@ -653,10 +650,10 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
     }
 }
 
-type ErrorMessage = Option<(Span, String)>;
+pub type ErrorMessage = Option<(Span, String)>;
 
 #[derive(Clone, PartialEq, Eq)]
-enum ResolveResult<T> {
+pub enum ResolveResult<T> {
     Failed(ErrorMessage), // Failed to resolve the name, optional helpful error message.
     Indeterminate, // Couldn't determine due to unresolved globs.
     Success(T), // Successfully resolved the import.
@@ -670,6 +667,13 @@ impl<T> ResolveResult<T> {
             Success(t) => f(t),
         }
     }
+
+    fn success(self) -> Option<T> {
+        match self {
+            Success(t) => Some(t),
+            _ => None,
+        }
+    }
 }
 
 enum FallbackSuggestion {
@@ -795,7 +799,7 @@ pub struct ModuleS<'a> {
     is_public: bool,
     is_extern_crate: bool,
 
-    children: RefCell<HashMap<(Name, Namespace), NameBinding<'a>>>,
+    children: RefCell<HashMap<(Name, Namespace), NameResolution<'a>>>,
     imports: RefCell<Vec<ImportDirective>>,
 
     // The anonymous children of this node. Anonymous children are pseudo-
@@ -814,8 +818,7 @@ pub struct ModuleS<'a> {
     // entry block for `f`.
     anonymous_children: RefCell<NodeMap<Module<'a>>>,
 
-    // The status of resolving each import in this module.
-    import_resolutions: RefCell<HashMap<(Name, Namespace), ImportResolution<'a>>>,
+    shadowed_traits: RefCell<Vec<&'a NameBinding<'a>>>,
 
     // The number of unresolved globs that this module exports.
     glob_count: Cell<usize>,
@@ -847,7 +850,7 @@ impl<'a> ModuleS<'a> {
             children: RefCell::new(HashMap::new()),
             imports: RefCell::new(Vec::new()),
             anonymous_children: RefCell::new(NodeMap()),
-            import_resolutions: RefCell::new(HashMap::new()),
+            shadowed_traits: RefCell::new(Vec::new()),
             glob_count: Cell::new(0),
             pub_count: Cell::new(0),
             pub_glob_count: Cell::new(0),
@@ -856,26 +859,60 @@ impl<'a> ModuleS<'a> {
         }
     }
 
-    fn get_child(&self, name: Name, ns: Namespace) -> Option<NameBinding<'a>> {
-        self.children.borrow().get(&(name, ns)).cloned()
+    fn resolve_name(&self, name: Name, ns: Namespace, allow_private_imports: bool)
+                    -> ResolveResult<&'a NameBinding<'a>> {
+        let glob_count =
+            if allow_private_imports { self.glob_count.get() } else { self.pub_glob_count.get() };
+
+        self.children.borrow().get(&(name, ns)).cloned().unwrap_or_default().result(glob_count)
+            .and_then(|binding| {
+                let allowed = allow_private_imports || !binding.is_import() || binding.is_public();
+                if allowed { Success(binding) } else { Failed(None) }
+            })
+    }
+
+    // Define the name or return the existing binding if there is a collision.
+    fn try_define_child(&self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>)
+                        -> Result<(), &'a NameBinding<'a>> {
+        let mut children = self.children.borrow_mut();
+        let resolution = children.entry((name, ns)).or_insert_with(Default::default);
+
+        // FIXME #31379: We can use methods from imported traits shadowed by non-import items
+        if let Some(old_binding) = resolution.binding {
+            if !old_binding.is_import() && binding.is_import() {
+                if let Some(Def::Trait(_)) = binding.def() {
+                    self.shadowed_traits.borrow_mut().push(binding);
+                }
+            }
+        }
+
+        resolution.try_define(binding)
+    }
+
+    fn increment_outstanding_references_for(&self, name: Name, ns: Namespace) {
+        let mut children = self.children.borrow_mut();
+        children.entry((name, ns)).or_insert_with(Default::default).outstanding_references += 1;
     }
 
-    // If the name is not yet defined, define the name and return None.
-    // Otherwise, return the existing definition.
-    fn try_define_child(&self, name: Name, ns: Namespace, binding: NameBinding<'a>)
-                        -> Option<NameBinding<'a>> {
-        match self.children.borrow_mut().entry((name, ns)) {
-            hash_map::Entry::Vacant(entry) => { entry.insert(binding); None }
-            hash_map::Entry::Occupied(entry) => { Some(entry.get().clone()) },
+    fn decrement_outstanding_references_for(&self, name: Name, ns: Namespace) {
+        match self.children.borrow_mut().get_mut(&(name, ns)).unwrap().outstanding_references {
+            0 => panic!("No more outstanding references!"),
+            ref mut outstanding_references => { *outstanding_references -= 1; }
         }
     }
 
-    fn for_each_local_child<F: FnMut(Name, Namespace, &NameBinding<'a>)>(&self, mut f: F) {
-        for (&(name, ns), name_binding) in self.children.borrow().iter() {
-            if !name_binding.is_extern_crate() {
+    fn for_each_child<F: FnMut(Name, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
+        for (&(name, ns), name_resolution) in self.children.borrow().iter() {
+            name_resolution.binding.map(|binding| f(name, ns, binding));
+        }
+    }
+
+    fn for_each_local_child<F: FnMut(Name, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
+        self.for_each_child(|name, ns, name_binding| {
+            if !name_binding.is_import() && !name_binding.is_extern_crate() {
                 f(name, ns, name_binding)
             }
-        }
+        })
     }
 
     fn def_id(&self) -> Option<DefId> {
@@ -951,21 +988,27 @@ 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,
+        const GLOB_IMPORTED = 1 << 4,
     }
 }
 
 // Records a possibly-private value, type, or module definition.
-#[derive(Clone, Debug)]
+#[derive(Debug)]
 pub struct NameBinding<'a> {
-    modifiers: DefModifiers, // see note in ImportResolution about how to use this
-    def_or_module: DefOrModule<'a>,
+    modifiers: DefModifiers,
+    kind: NameBindingKind<'a>,
     span: Option<Span>,
 }
 
-#[derive(Clone, Debug)]
-enum DefOrModule<'a> {
+#[derive(Debug)]
+enum NameBindingKind<'a> {
     Def(Def),
     Module(Module<'a>),
+    Import {
+        binding: &'a NameBinding<'a>,
+        id: NodeId,
+    },
 }
 
 impl<'a> NameBinding<'a> {
@@ -976,20 +1019,22 @@ impl<'a> NameBinding<'a> {
             DefModifiers::empty()
         } | DefModifiers::IMPORTABLE;
 
-        NameBinding { modifiers: modifiers, def_or_module: DefOrModule::Module(module), span: span }
+        NameBinding { modifiers: modifiers, kind: NameBindingKind::Module(module), span: span }
     }
 
     fn module(&self) -> Option<Module<'a>> {
-        match self.def_or_module {
-            DefOrModule::Module(ref module) => Some(module),
-            DefOrModule::Def(_) => None,
+        match self.kind {
+            NameBindingKind::Module(module) => Some(module),
+            NameBindingKind::Def(_) => None,
+            NameBindingKind::Import { binding, .. } => binding.module(),
         }
     }
 
     fn def(&self) -> Option<Def> {
-        match self.def_or_module {
-            DefOrModule::Def(def) => Some(def),
-            DefOrModule::Module(ref module) => module.def,
+        match self.kind {
+            NameBindingKind::Def(def) => Some(def),
+            NameBindingKind::Module(module) => module.def,
+            NameBindingKind::Import { binding, .. } => binding.def(),
         }
     }
 
@@ -1009,6 +1054,13 @@ impl<'a> NameBinding<'a> {
     fn is_extern_crate(&self) -> bool {
         self.module().map(|module| module.is_extern_crate).unwrap_or(false)
     }
+
+    fn is_import(&self) -> bool {
+        match self.kind {
+            NameBindingKind::Import { .. } => true,
+            _ => false,
+        }
+    }
 }
 
 /// Interns the names of the primitive types.
@@ -1112,6 +1164,7 @@ pub struct Resolver<'a, 'tcx: 'a> {
 
 pub struct ResolverArenas<'a> {
     modules: arena::TypedArena<ModuleS<'a>>,
+    name_bindings: arena::TypedArena<NameBinding<'a>>,
 }
 
 #[derive(PartialEq)]
@@ -1177,6 +1230,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     fn arenas() -> ResolverArenas<'a> {
         ResolverArenas {
             modules: arena::TypedArena::new(),
+            name_bindings: arena::TypedArena::new(),
         }
     }
 
@@ -1188,6 +1242,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         self.arenas.modules.alloc(ModuleS::new(parent_link, def, external, is_public))
     }
 
+    fn new_name_binding(&self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> {
+        self.arenas.name_bindings.alloc(name_binding)
+    }
+
     fn new_extern_crate_module(&self, parent_link: ParentLink<'a>, def: Def) -> Module<'a> {
         let mut module = ModuleS::new(parent_link, Some(def), false, true);
         module.is_extern_crate = true;
@@ -1199,14 +1257,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     }
 
     #[inline]
-    fn record_import_use(&mut self, name: Name, ns: Namespace, resolution: &ImportResolution<'a>) {
-        let import_id = resolution.id;
-        self.used_imports.insert((import_id, ns));
-        match resolution.target.as_ref().and_then(|target| target.target_module.def_id()) {
-            Some(DefId { krate, .. }) => { self.used_crates.insert(krate); }
-            _ => {}
+    fn record_use(&mut self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>) {
+        // track extern crates for unused_extern_crate lint
+        if let Some(DefId { krate, .. }) = binding.module().and_then(ModuleS::def_id) {
+            self.used_crates.insert(krate);
+        }
+
+        let import_id = match binding.kind {
+            NameBindingKind::Import { id, .. } => id,
+            _ => return,
         };
 
+        self.used_imports.insert((import_id, ns));
+
         if !self.make_glob_map {
             return;
         }
@@ -1237,8 +1300,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                      lp: LastPrivate)
                                      -> ResolveResult<(Module<'a>, LastPrivate)> {
         fn search_parent_externals<'a>(needle: Name, module: Module<'a>) -> Option<Module<'a>> {
-            match module.get_child(needle, TypeNS) {
-                Some(ref binding) if binding.is_extern_crate() => Some(module),
+            match module.resolve_name(needle, TypeNS, false) {
+                Success(binding) if binding.is_extern_crate() => Some(module),
                 _ => match module.parent_link {
                     ModuleParentLink(ref parent, _) => {
                         search_parent_externals(needle, parent)
@@ -1295,20 +1358,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                            name);
                     return Indeterminate;
                 }
-                Success((target, used_proxy)) => {
+                Success(binding) => {
                     // 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() {
-                        // track extern crates for unused_extern_crate lint
-                        if let Some(did) = module_def.def_id() {
-                            self.used_crates.insert(did.krate);
-                        }
-
+                    if let Some(module_def) = binding.module() {
                         search_module = module_def;
 
                         // Keep track of the closest private module used
                         // when resolving this import chain.
-                        if !used_proxy && !search_module.is_public {
+                        if !binding.is_public() {
                             if let Some(did) = search_module.def_id() {
                                 closest_private = LastMod(DependsOn(did));
                             }
@@ -1399,7 +1457,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;
@@ -1433,7 +1491,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                      name: Name,
                                      namespace: Namespace,
                                      record_used: bool)
-                                     -> ResolveResult<(Target<'a>, bool)> {
+                                     -> ResolveResult<&'a NameBinding<'a>> {
         debug!("(resolving item in lexical scope) resolving `{}` in namespace {:?} in `{}`",
                name,
                namespace,
@@ -1455,10 +1513,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) => {
                     // We found the module.
                     debug!("(resolving item in lexical scope) found name in module, done");
-                    return Success((target, used_reexport));
+                    return Success(binding);
                 }
             }
 
@@ -1552,51 +1610,24 @@ 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
-    /// passed through a public re-export proxy.
     fn resolve_name_in_module(&mut self,
-                              module_: Module<'a>,
+                              module: Module<'a>,
                               name: Name,
                               namespace: Namespace,
                               allow_private_imports: bool,
                               record_used: bool)
-                              -> ResolveResult<(Target<'a>, bool)> {
-        debug!("(resolving name in module) resolving `{}` in `{}`",
-               name,
-               module_to_string(&*module_));
+                              -> ResolveResult<&'a NameBinding<'a>> {
+        debug!("(resolving name in module) resolving `{}` in `{}`", name, module_to_string(module));
 
-        // First, check the direct children of the module.
-        build_reduced_graph::populate_module_if_necessary(self, module_);
-
-        if let Some(binding) = module_.get_child(name, namespace) {
-            debug!("(resolving name in module) found node as child");
-            return Success((Target::new(module_, binding, Shadowable::Never), false));
-        }
-
-        // Check the list of resolved imports.
-        match module_.import_resolutions.borrow().get(&(name, namespace)) {
-            Some(import_resolution) if allow_private_imports || import_resolution.is_public => {
-                if import_resolution.is_public && import_resolution.outstanding_references != 0 {
-                    debug!("(resolving name in module) import unresolved; bailing out");
-                    return Indeterminate;
-                }
-                if let Some(target) = import_resolution.target.clone() {
-                    debug!("(resolving name in module) resolved to import");
-                    if record_used {
-                        self.record_import_use(name, namespace, &import_resolution);
-                    }
-                    return Success((target, true));
-                }
+        build_reduced_graph::populate_module_if_necessary(self, module);
+        module.resolve_name(name, namespace, allow_private_imports).and_then(|binding| {
+            if record_used {
+                self.record_use(name, namespace, binding);
             }
-            Some(..) | None => {} // Continue.
-        }
-
-        // We're out of luck.
-        debug!("(resolving name in module) failed to resolve `{}`", name);
-        return Failed(None);
+            Success(binding)
+        })
     }
 
     fn report_unresolved_imports(&mut self, module_: Module<'a>) {
@@ -1659,22 +1690,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             Some(name) => {
                 build_reduced_graph::populate_module_if_necessary(self, &orig_module);
 
-                match orig_module.get_child(name, TypeNS) {
-                    None => {
-                        debug!("!!! (with scope) didn't find `{}` in `{}`",
-                               name,
-                               module_to_string(&*orig_module));
-                    }
-                    Some(name_binding) => {
-                        match name_binding.module() {
-                            None => {
-                                debug!("!!! (with scope) didn't find module for `{}` in `{}`",
-                                       name,
-                                       module_to_string(&*orig_module));
-                            }
-                            Some(module_) => {
-                                self.current_module = module_;
-                            }
+                if let Success(name_binding) = orig_module.resolve_name(name, TypeNS, false) {
+                    match name_binding.module() {
+                        None => {
+                            debug!("!!! (with scope) didn't find module for `{}` in `{}`",
+                                   name,
+                                   module_to_string(orig_module));
+                        }
+                        Some(module) => {
+                            self.current_module = module;
                         }
                     }
                 }
@@ -2619,11 +2643,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?!");
@@ -2779,7 +2803,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
@@ -2917,15 +2941,12 @@ 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))
             }
             _ => return None,
         };
-        if let Some(DefId{krate: kid, ..}) = containing_module.def_id() {
-            self.used_crates.insert(kid);
-        }
         return Some(def);
     }
 
@@ -2976,7 +2997,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)))
             }
@@ -3014,12 +3035,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));
                     }
                 }
@@ -3063,8 +3084,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             if name_path.len() == 1 {
                 match this.primitive_type_table.primitive_types.get(last_name) {
                     Some(_) => None,
-                    None => this.current_module.get_child(*last_name, TypeNS)
-                                               .as_ref()
+                    None => this.current_module.resolve_name(*last_name, TypeNS, true).success()
                                                .and_then(NameBinding::module)
                 }
             } else {
@@ -3124,7 +3144,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
         // Look for a method in the current self type's impl module.
         if let Some(module) = get_module(self, path.span, &name_path) {
-            if let Some(binding) = module.get_child(name, ValueNS) {
+            if let Success(binding) = module.resolve_name(name, ValueNS, true) {
                 if let Some(Def::Method(did)) = binding.def() {
                     if is_static_method(self, did) {
                         return StaticMethod(path_names_to_string(&path, 0));
@@ -3447,32 +3467,26 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             // Look for trait children.
             build_reduced_graph::populate_module_if_necessary(self, &search_module);
 
-            for (&(_, ns), name_binding) in search_module.children.borrow().iter() {
-                if ns != TypeNS { continue }
+            search_module.for_each_child(|_, ns, name_binding| {
+                if ns != TypeNS { return }
                 let trait_def_id = match name_binding.def() {
                     Some(Def::Trait(trait_def_id)) => trait_def_id,
-                    Some(..) | None => continue,
+                    Some(..) | None => return,
                 };
                 if self.trait_item_map.contains_key(&(name, trait_def_id)) {
                     add_trait_info(&mut found_traits, trait_def_id, name);
+                    let trait_name = self.get_trait_name(trait_def_id);
+                    self.record_use(trait_name, TypeNS, name_binding);
                 }
-            }
+            });
 
-            // 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,
-                    None => continue,
-                };
-                let did = match target.binding.def() {
-                    Some(Def::Trait(trait_def_id)) => trait_def_id,
-                    Some(..) | None => continue,
-                };
+            // Look for shadowed traits.
+            for binding in search_module.shadowed_traits.borrow().iter() {
+                let did = binding.def().unwrap().def_id();
                 if self.trait_item_map.contains_key(&(name, did)) {
                     add_trait_info(&mut found_traits, did, name);
                     let trait_name = self.get_trait_name(did);
-                    self.record_import_use(trait_name, TypeNS, &import);
+                    self.record_use(trait_name, TypeNS, binding);
                 }
             }
 
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 3d2300e44c4..6667e489870 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -11,10 +11,9 @@
 use self::ImportDirectiveSubclass::*;
 
 use DefModifiers;
-use DefOrModule;
 use Module;
 use Namespace::{self, TypeNS, ValueNS};
-use NameBinding;
+use {NameBinding, NameBindingKind};
 use ResolveResult;
 use ResolveResult::*;
 use Resolver;
@@ -26,7 +25,6 @@ use build_reduced_graph;
 
 use rustc::lint;
 use rustc::middle::def::*;
-use rustc::middle::def_id::DefId;
 use rustc::middle::privacy::*;
 
 use syntax::ast::{NodeId, Name};
@@ -78,66 +76,74 @@ 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,
-}
+    // 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, binding: &'a NameBinding<'a>) -> NameBinding<'a> {
+        let mut modifiers = match self.is_public {
+            true => DefModifiers::PUBLIC | DefModifiers::IMPORTABLE,
+            false => DefModifiers::empty(),
+        };
+        if let GlobImport = self.subclass {
+            modifiers = modifiers | DefModifiers::GLOB_IMPORTED;
+        }
+        if self.shadowable == Shadowable::Always {
+            modifiers = modifiers | DefModifiers::PRELUDE;
+        }
 
-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,
+        NameBinding {
+            kind: NameBindingKind::Import { binding: binding, id: self.id },
+            span: Some(self.span),
+            modifiers: modifiers,
         }
     }
 }
 
-#[derive(Debug)]
-/// An ImportResolution records what we know about an imported name in a given namespace.
-/// More specifically, it records the number of unresolved `use` directives that import the name,
-/// the `use` directive importing the name in the namespace, and the `NameBinding` to which the
-/// name in the namespace resolves (if applicable).
-/// Different `use` directives may import the same name in different namespaces.
-pub struct ImportResolution<'a> {
-    // When outstanding_references reaches zero, outside modules can count on the targets being
-    // correct. Before then, all bets are off; future `use` directives could override the name.
-    // Since shadowing is forbidden, the only way outstanding_references > 1 in a legal program
-    // is if the name is imported by exactly two `use` directives, one of which resolves to a
-    // value and the other of which resolves to a type.
+#[derive(Clone, Default)]
+/// Records information about the resolution of a name in a module.
+pub struct NameResolution<'a> {
+    /// The number of unresolved single imports that could define the name.
     pub outstanding_references: usize,
-
-    /// Whether this resolution came from a `use` or a `pub use`.
-    pub is_public: bool,
-
-    /// Resolution of the name in the namespace
-    pub target: Option<Target<'a>>,
-
-    /// The source node of the `use` directive
-    pub id: NodeId,
+    /// The least shadowable known binding for this name, or None if there are no known bindings.
+    pub binding: Option<&'a NameBinding<'a>>,
 }
 
-impl<'a> ImportResolution<'a> {
-    pub fn new(id: NodeId, is_public: bool) -> Self {
-        ImportResolution {
-            outstanding_references: 0,
-            id: id,
-            target: None,
-            is_public: is_public,
+impl<'a> NameResolution<'a> {
+    pub fn result(&self, outstanding_globs: usize) -> ResolveResult<&'a NameBinding<'a>> {
+        // If no unresolved imports (single or glob) can define the name, self.binding is final.
+        if self.outstanding_references == 0 && outstanding_globs == 0 {
+            return self.binding.map(Success).unwrap_or(Failed(None));
+        }
+
+        if let Some(binding) = self.binding {
+            // Single imports will never be shadowable by other single or glob imports.
+            if !binding.defined_with(DefModifiers::GLOB_IMPORTED) { return Success(binding); }
+            // Non-PRELUDE glob imports will never be shadowable by other glob imports.
+            if self.outstanding_references == 0 && !binding.defined_with(DefModifiers::PRELUDE) {
+                return Success(binding);
+            }
         }
+
+        Indeterminate
     }
 
-    pub fn shadowable(&self) -> Shadowable {
-        match self.target {
-            Some(ref target) => target.shadowable,
-            None => Shadowable::Always,
+    // Define the name or return the existing binding if there is a collision.
+    pub fn try_define(&mut self, binding: &'a NameBinding<'a>) -> Result<(), &'a NameBinding<'a>> {
+        let is_prelude = |binding: &NameBinding| binding.defined_with(DefModifiers::PRELUDE);
+        let old_binding = match self.binding {
+            Some(_) if is_prelude(binding) => return Ok(()),
+            Some(old_binding) if !is_prelude(old_binding) => old_binding,
+            _ => { self.binding = Some(binding); return Ok(()); }
+        };
+
+        // FIXME #31337: We currently allow items to shadow glob-imported re-exports.
+        if !old_binding.is_import() && binding.defined_with(DefModifiers::GLOB_IMPORTED) {
+            if let NameBindingKind::Import { binding, .. } = binding.kind {
+                if binding.is_import() { return Ok(()); }
+            }
         }
+
+        Err(old_binding)
     }
 }
 
@@ -203,38 +209,18 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
 
     /// Resolves an `ImportResolvingError` into the correct enum discriminant
     /// and passes that on to `resolve_error`.
-    fn import_resolving_error(&self, e: ImportResolvingError) {
+    fn import_resolving_error(&self, e: ImportResolvingError<'b>) {
         // If it's a single failed import then create a "fake" import
         // resolution for it so that later resolve stages won't complain.
         if let SingleImport(target, _) = e.import_directive.subclass {
-            let mut import_resolutions = e.source_module.import_resolutions.borrow_mut();
-
-            let resolution = import_resolutions.entry((target, ValueNS)).or_insert_with(|| {
-                debug!("(resolving import error) adding import resolution for `{}`",
-                       target);
-
-                ImportResolution::new(e.import_directive.id,
-                                      e.import_directive.is_public)
+            let dummy_binding = self.resolver.new_name_binding(NameBinding {
+                modifiers: DefModifiers::PRELUDE,
+                kind: NameBindingKind::Def(Def::Err),
+                span: None,
             });
 
-            if resolution.target.is_none() {
-                debug!("(resolving import error) adding fake target to import resolution of `{}`",
-                       target);
-
-                let name_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);
-            }
+            let _ = e.source_module.try_define_child(target, ValueNS, dummy_binding);
+            let _ = e.source_module.try_define_child(target, TypeNS, dummy_binding);
         }
 
         let path = import_path_to_string(&e.import_directive.module_path,
@@ -373,70 +359,6 @@ 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`.
-    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) {
-        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() {
-                // track the extern crate as used.
-                if let Some(DefId { krate, .. }) = name_binding.module().unwrap().def_id() {
-                    self.resolver.used_crates.insert(krate);
-                }
-            }
-            return (Success((module, name_binding)), false)
-        }
-
-        // If there is an unresolved glob at this point in the containing module, bail out.
-        // We don't know enough to be able to resolve the name.
-        if module.pub_glob_count.get() > 0 {
-            return (Indeterminate, false);
-        }
-
-        match module.import_resolutions.borrow().get(&(name, ns)) {
-            // The containing module definitely doesn't have an exported import with the
-            // name in question. We can therefore accurately report that names are unbound.
-            None => (Failed(None), false),
-
-            // The name is an import which has been fully resolved, so we just follow it.
-            Some(resolution) if resolution.outstanding_references == 0 => {
-                // Import resolutions must be declared with "pub" in order to be exported.
-                if !resolution.is_public {
-                    return (Failed(None), false);
-                }
-
-                let target = resolution.target.clone();
-                if let Some(Target { target_module, binding, shadowable: _ }) = target {
-                    self.resolver.record_import_use(name, ns, &resolution);
-                    (Success((target_module, binding)), true)
-                } else {
-                    (Failed(None), false)
-                }
-            }
-
-            // If module is the same module whose import we are resolving and
-            // it has an unresolved import with the same name as `name`, then the user
-            // is actually trying to import an item that is declared in the same scope
-            //
-            // e.g
-            // use self::submodule;
-            // pub mod submodule;
-            //
-            // In this case we continue as if we resolved the import and let
-            // check_for_conflicts_between_imports_and_items handle the conflict
-            Some(_) => match (importing_module.def_id(), module.def_id()) {
-                (Some(id1), Some(id2)) if id1 == id2 => (Failed(None), false),
-                _ => (Indeterminate, false)
-            },
-        }
-    }
-
     fn resolve_single_import(&mut self,
                              module_: Module<'b>,
                              target_module: Module<'b>,
@@ -463,16 +385,28 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
             }
         };
 
+        // If this is a circular import, we temporarily count it as determined so that
+        // it fails (as opposed to being indeterminate) when nothing else can define it.
+        if target_module.def_id() == module_.def_id() && source == target {
+            module_.decrement_outstanding_references_for(target, ValueNS);
+            module_.decrement_outstanding_references_for(target, TypeNS);
+        }
+
         // We need to resolve both namespaces for this to succeed.
-        let (value_result, value_used_reexport) =
-            self.resolve_name_in_module(target_module, source, ValueNS, module_);
-        let (type_result, type_used_reexport) =
-            self.resolve_name_in_module(target_module, source, TypeNS, module_);
+        let value_result =
+            self.resolver.resolve_name_in_module(target_module, source, ValueNS, false, true);
+        let type_result =
+            self.resolver.resolve_name_in_module(target_module, source, TypeNS, false, true);
+
+        if target_module.def_id() == module_.def_id() && source == target {
+            module_.increment_outstanding_references_for(target, ValueNS);
+            module_.increment_outstanding_references_for(target, TypeNS);
+        }
 
         match (&value_result, &type_result) {
-            (&Success((_, ref name_binding)), _) if !value_used_reexport &&
-                                                    directive.is_public &&
-                                                    !name_binding.is_public() => {
+            (&Success(name_binding), _) if !name_binding.is_import() &&
+                                           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 +415,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                     .emit();
             }
 
-            (_, &Success((_, ref name_binding))) if !type_used_reexport &&
-                                                    directive.is_public => {
+            (_, &Success(name_binding)) if !name_binding.is_import() && directive.is_public => {
                 if !name_binding.is_public() {
                     let msg = format!("`{}` is private, and cannot be reexported", source);
                     let note_msg =
@@ -504,120 +437,47 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
             _ => {}
         }
 
-        let mut lev_suggestion = "".to_owned();
         match (&value_result, &type_result) {
             (&Indeterminate, _) | (_, &Indeterminate) => return Indeterminate,
             (&Failed(_), &Failed(_)) => {
                 let children = target_module.children.borrow();
                 let names = children.keys().map(|&(ref name, _)| name);
-                if let Some(name) = find_best_match_for_name(names, &source.as_str(), None) {
-                    lev_suggestion = format!(". Did you mean to use `{}`?", name);
-                } else {
-                    let resolutions = target_module.import_resolutions.borrow();
-                    let names = resolutions.keys().map(|&(ref name, _)| name);
-                    if let Some(name) = find_best_match_for_name(names,
-                                                                 &source.as_str(),
-                                                                 None) {
-                        lev_suggestion =
-                            format!(". Did you mean to use the re-exported import `{}`?", name);
-                    }
-                }
+                let lev_suggestion = match find_best_match_for_name(names, &source.as_str(), None) {
+                    Some(name) => format!(". Did you mean to use `{}`?", name),
+                    None => "".to_owned(),
+                };
+                let msg = format!("There is no `{}` in `{}`{}",
+                                  source,
+                                  module_to_string(target_module), lev_suggestion);
+                return Failed(Some((directive.span, msg)));
             }
             _ => (),
         }
 
-        let mut value_used_public = false;
-        let mut type_used_public = false;
-
-        // We've successfully resolved the import. Write the results in.
-        let mut import_resolutions = module_.import_resolutions.borrow_mut();
-
-        {
-            let mut check_and_write_import = |namespace, result, used_public: &mut bool| {
-                let result: &ResolveResult<(Module<'b>, NameBinding)> = result;
-
-                let import_resolution = import_resolutions.get_mut(&(target, namespace)).unwrap();
-                let namespace_name = match namespace {
-                    TypeNS => "type",
-                    ValueNS => "value",
-                };
-
-                match *result {
-                    Success((ref target_module, ref name_binding)) => {
-                        debug!("(resolving single import) found {:?} target: {:?}",
-                               namespace_name,
-                               name_binding.def());
-                        self.check_for_conflicting_import(&import_resolution,
-                                                          directive.span,
-                                                          target,
-                                                          namespace);
-
-                        self.check_that_import_is_importable(&name_binding,
-                                                             directive.span,
-                                                             target);
-
-                        import_resolution.target = Some(Target::new(target_module,
-                                                                    name_binding.clone(),
-                                                                    directive.shadowable));
-                        import_resolution.id = directive.id;
-                        import_resolution.is_public = directive.is_public;
-
-                        self.add_export(module_, target, &import_resolution);
-                        *used_public = name_binding.is_public();
-                    }
-                    Failed(_) => {
-                        // Continue.
-                    }
-                    Indeterminate => {
-                        panic!("{:?} result should be known at this point", namespace_name);
-                    }
+        for &(ns, result) in &[(ValueNS, &value_result), (TypeNS, &type_result)] {
+            if let Success(binding) = *result {
+                if !binding.defined_with(DefModifiers::IMPORTABLE) {
+                    let msg = format!("`{}` is not directly importable", target);
+                    span_err!(self.resolver.session, directive.span, E0253, "{}", &msg);
                 }
 
-                self.check_for_conflicts_between_imports_and_items(module_,
-                                                                   import_resolution,
-                                                                   directive.span,
-                                                                   (target, namespace));
-            };
-            check_and_write_import(ValueNS, &value_result, &mut value_used_public);
-            check_and_write_import(TypeNS, &type_result, &mut type_used_public);
-        }
-
-        if let (&Failed(_), &Failed(_)) = (&value_result, &type_result) {
-            let msg = format!("There is no `{}` in `{}`{}",
-                              source,
-                              module_to_string(target_module), lev_suggestion);
-            return Failed(Some((directive.span, msg)));
+                self.define(module_, target, ns, directive.import(binding));
+            }
         }
 
-        let value_used_public = value_used_reexport || value_used_public;
-        let type_used_public = type_used_reexport || type_used_public;
-
-        let value_def_and_priv = {
-            let import_resolution_value = import_resolutions.get_mut(&(target, ValueNS)).unwrap();
-            assert!(import_resolution_value.outstanding_references >= 1);
-            import_resolution_value.outstanding_references -= 1;
-
-            // 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();
-                let last_private = if value_used_public { lp } else { DependsOn(def.def_id()) };
-                (def, last_private)
-            })
-        };
-
-        let type_def_and_priv = {
-            let import_resolution_type = import_resolutions.get_mut(&(target, TypeNS)).unwrap();
-            assert!(import_resolution_type.outstanding_references >= 1);
-            import_resolution_type.outstanding_references -= 1;
+        // 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.
+        module_.decrement_outstanding_references_for(target, ValueNS);
+        module_.decrement_outstanding_references_for(target, TypeNS);
 
-            import_resolution_type.target.as_ref().map(|target| {
-                let def = target.binding.def().unwrap();
-                let last_private = if type_used_public { lp } else { DependsOn(def.def_id()) };
-                (def, last_private)
-            })
+        let def_and_priv = |binding: &NameBinding| {
+            let def = binding.def().unwrap();
+            let last_private = if binding.is_public() { lp } else { DependsOn(def.def_id()) };
+            (def, last_private)
         };
+        let value_def_and_priv = value_result.success().map(&def_and_priv);
+        let type_def_and_priv = type_result.success().map(&def_and_priv);
 
         let import_lp = LastImport {
             value_priv: value_def_and_priv.map(|(_, p)| p),
@@ -626,22 +486,13 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
             type_used: Used,
         };
 
-        if let Some((def, _)) = value_def_and_priv {
-            self.resolver.def_map.borrow_mut().insert(directive.id,
-                                                      PathResolution {
-                                                          base_def: def,
-                                                          last_private: import_lp,
-                                                          depth: 0,
-                                                      });
-        }
-        if let Some((def, _)) = type_def_and_priv {
-            self.resolver.def_map.borrow_mut().insert(directive.id,
-                                                      PathResolution {
-                                                          base_def: def,
-                                                          last_private: import_lp,
-                                                          depth: 0,
-                                                      });
-        }
+        let write_path_resolution = |(def, _)| {
+            let path_resolution =
+                PathResolution { base_def: def, last_private: import_lp, depth: 0 };
+            self.resolver.def_map.borrow_mut().insert(directive.id, path_resolution);
+        };
+        value_def_and_priv.map(&write_path_resolution);
+        type_def_and_priv.map(&write_path_resolution);
 
         debug!("(resolving single import) successfully resolved import");
         return Success(());
@@ -654,76 +505,41 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
     fn resolve_glob_import(&mut self,
                            module_: Module<'b>,
                            target_module: Module<'b>,
-                           import_directive: &ImportDirective,
+                           directive: &ImportDirective,
                            lp: LastPrivate)
                            -> ResolveResult<()> {
-        let id = import_directive.id;
-        let is_public = import_directive.is_public;
-
-        // This function works in a highly imperative manner; it eagerly adds
-        // everything it can to the list of import resolutions of the module
-        // node.
-        debug!("(resolving glob import) resolving glob import {}", id);
-
-        // We must bail out if the node has unresolved imports of any kind
-        // (including globs).
-        if (*target_module).pub_count.get() > 0 {
+        // We must bail out if the node has unresolved imports of any kind (including globs).
+        if target_module.pub_count.get() > 0 {
             debug!("(resolving glob import) target module has unresolved pub imports; bailing out");
-            return ResolveResult::Indeterminate;
-        }
-
-        // Add all resolved imports from the containing module.
-        let import_resolutions = target_module.import_resolutions.borrow();
-
-        if module_.import_resolutions.borrow_state() != ::std::cell::BorrowState::Unused {
-            // In this case, target_module == module_
-            // This means we are trying to glob import a module into itself,
-            // and it is a no-go
-            debug!("(resolving glob imports) target module is current module; giving up");
-            return ResolveResult::Failed(Some((import_directive.span,
-                                               "Cannot glob-import a module into itself.".into())));
+            return Indeterminate;
         }
 
-        for (&(name, ns), target_import_resolution) in import_resolutions.iter() {
-            debug!("(resolving glob import) writing module resolution {} into `{}`",
-                   name,
-                   module_to_string(module_));
-
-            // Here we merge two import resolutions.
-            let mut import_resolutions = module_.import_resolutions.borrow_mut();
-            let mut dest_import_resolution =
-                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 => {
-                    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());
-                    self.add_export(module_, name, &dest_import_resolution);
-                }
-                _ => {}
-            }
+        if module_.def_id() == target_module.def_id() {
+            // This means we are trying to glob import a module into itself, and it is a no-go
+            let msg = "Cannot glob-import a module into itself.".into();
+            return Failed(Some((directive.span, msg)));
         }
 
         // Add all children from the containing module.
         build_reduced_graph::populate_module_if_necessary(self.resolver, target_module);
-
-        target_module.for_each_local_child(|name, ns, name_binding| {
-            self.merge_import_resolution(module_,
-                                         target_module,
-                                         import_directive,
-                                         (name, ns),
-                                         name_binding.clone());
+        target_module.for_each_child(|name, ns, binding| {
+            if !binding.defined_with(DefModifiers::IMPORTABLE | DefModifiers::PUBLIC) { return }
+            self.define(module_, name, ns, directive.import(binding));
+
+            if ns == TypeNS && directive.is_public &&
+               binding.defined_with(DefModifiers::PRIVATE_VARIANT) {
+                let msg = format!("variant `{}` is private, and cannot be reexported (error \
+                                   E0364), consider declaring its enum as `pub`", name);
+                self.resolver.session.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
+                                               directive.id,
+                                               directive.span,
+                                               msg);
+            }
         });
 
         // Record the destination of this import
         if let Some(did) = target_module.def_id() {
-            self.resolver.def_map.borrow_mut().insert(id,
+            self.resolver.def_map.borrow_mut().insert(directive.id,
                                                       PathResolution {
                                                           base_def: Def::Mod(did),
                                                           last_private: lp,
@@ -732,196 +548,77 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
         }
 
         debug!("(resolving glob import) successfully resolved import");
-        return ResolveResult::Success(());
-    }
-
-    fn merge_import_resolution(&mut self,
-                               module_: Module<'b>,
-                               containing_module: Module<'b>,
-                               import_directive: &ImportDirective,
-                               (name, ns): (Name, Namespace),
-                               name_binding: NameBinding<'b>) {
-        let id = import_directive.id;
-        let is_public = import_directive.is_public;
-
-        let mut import_resolutions = module_.import_resolutions.borrow_mut();
-        let dest_import_resolution = import_resolutions.entry((name, ns)).or_insert_with(|| {
-            ImportResolution::new(id, is_public)
-        });
-
-        debug!("(resolving glob import) writing resolution `{}` in `{}` to `{}`",
-               name,
-               module_to_string(&*containing_module),
-               module_to_string(module_));
-
-        // Merge the child item into the import resolution.
-        let modifier = DefModifiers::IMPORTABLE | DefModifiers::PUBLIC;
-
-        if ns == TypeNS && is_public && name_binding.defined_with(DefModifiers::PRIVATE_VARIANT) {
-            let msg = format!("variant `{}` is private, and cannot be reexported (error \
-                               E0364), consider declaring its enum as `pub`", name);
-            self.resolver.session.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
-                                           import_directive.id,
-                                           import_directive.span,
-                                           msg);
-        }
-
-        if name_binding.defined_with(modifier) {
-            let namespace_name = match ns {
-                TypeNS => "type",
-                ValueNS => "value",
-            };
-            debug!("(resolving glob import) ... for {} target", namespace_name);
-            if dest_import_resolution.shadowable() == Shadowable::Never {
-                let msg = format!("a {} named `{}` has already been imported in this module",
-                                 namespace_name,
-                                 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.id = id;
-                dest_import_resolution.is_public = is_public;
-                self.add_export(module_, name, &dest_import_resolution);
-            }
-        }
-
-        self.check_for_conflicts_between_imports_and_items(module_,
-                                                           dest_import_resolution,
-                                                           import_directive.span,
-                                                           (name, ns));
-    }
-
-    fn add_export(&mut self, module: Module<'b>, name: Name, resolution: &ImportResolution<'b>) {
-        if !resolution.is_public { return }
-        let node_id = match module.def_id() {
-            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() {
-            Some(def) => Export { name: name, def_id: def.def_id() },
-            None => return,
-        };
-        self.resolver.export_map.entry(node_id).or_insert(Vec::new()).push(export);
+        return Success(());
     }
 
-    /// Checks that imported names and items don't have the same name.
-    fn check_for_conflicting_import(&mut self,
-                                    import_resolution: &ImportResolution,
-                                    import_span: Span,
-                                    name: Name,
-                                    namespace: Namespace) {
-        let target = &import_resolution.target;
-        debug!("check_for_conflicting_import: {}; target exists: {}",
-               name,
-               target.is_some());
-
-        match *target {
-            Some(ref target) if target.shadowable != Shadowable::Always => {
-                let ns_word = match namespace {
-                    TypeNS => {
-                        match target.binding.module() {
-                            Some(ref module) if module.is_normal() => "module",
-                            Some(ref module) if module.is_trait() => "trait",
-                            _ => "type",
-                        }
-                    }
-                    ValueNS => "value",
-                };
-                let use_id = import_resolution.id;
-                let item = self.resolver.ast_map.expect_item(use_id);
-                let mut err = struct_span_err!(self.resolver.session,
-                                               import_span,
-                                               E0252,
-                                               "a {} named `{}` has already been imported \
-                                                in this module",
-                                               ns_word,
-                                               name);
-                span_note!(&mut err,
-                           item.span,
-                           "previous import of `{}` here",
-                           name);
-                err.emit();
+    fn define(&mut self,
+              parent: Module<'b>,
+              name: Name,
+              ns: Namespace,
+              binding: NameBinding<'b>) {
+        let binding = self.resolver.new_name_binding(binding);
+        if let Err(old_binding) = parent.try_define_child(name, ns, binding) {
+            self.report_conflict(name, ns, binding, old_binding);
+        } else if binding.is_public() { // Add to the export map
+            if let (Some(parent_def_id), Some(def)) = (parent.def_id(), binding.def()) {
+                let parent_node_id = self.resolver.ast_map.as_local_node_id(parent_def_id).unwrap();
+                let export = Export { name: name, def_id: def.def_id() };
+                self.resolver.export_map.entry(parent_node_id).or_insert(Vec::new()).push(export);
             }
-            Some(_) | None => {}
         }
     }
 
-    /// Checks that an import is actually importable
-    fn check_that_import_is_importable(&mut self,
-                                       name_binding: &NameBinding,
-                                       import_span: Span,
-                                       name: Name) {
-        if !name_binding.defined_with(DefModifiers::IMPORTABLE) {
-            let msg = format!("`{}` is not directly importable", name);
-            span_err!(self.resolver.session, import_span, E0253, "{}", &msg[..]);
-        }
-    }
-
-    /// Checks that imported names and items don't have the same name.
-    fn check_for_conflicts_between_imports_and_items(&mut self,
-                                                     module: Module<'b>,
-                                                     import: &ImportResolution<'b>,
-                                                     import_span: Span,
-                                                     (name, ns): (Name, Namespace)) {
-        // Check for item conflicts.
-        let name_binding = match module.get_child(name, ns) {
-            None => {
-                // There can't be any conflicts.
-                return;
-            }
-            Some(name_binding) => name_binding,
-        };
-
-        if ns == ValueNS {
-            match import.target {
-                Some(ref target) if target.shadowable != Shadowable::Always => {
-                    let mut err = struct_span_err!(self.resolver.session,
-                                                   import_span,
-                                                   E0255,
-                                                   "import `{}` conflicts with \
-                                                    value in this module",
-                                                   name);
-                    if let Some(span) = name_binding.span {
-                        err.span_note(span, "conflicting value here");
-                    }
-                    err.emit();
-                }
-                Some(_) | None => {}
-            }
-        } else {
-            match import.target {
-                Some(ref target) if target.shadowable != Shadowable::Always => {
-                    if name_binding.is_extern_crate() {
-                        let msg = format!("import `{0}` conflicts with imported crate \
-                                           in this module (maybe you meant `use {0}::*`?)",
-                                          name);
-                        span_err!(self.resolver.session, import_span, E0254, "{}", &msg[..]);
-                        return;
-                    }
-
-                    let (what, note) = match name_binding.module() {
-                        Some(ref module) if module.is_normal() =>
-                            ("existing submodule", "note conflicting module here"),
-                        Some(ref module) if module.is_trait() =>
-                            ("trait in this module", "note conflicting trait here"),
-                        _ => ("type in this module", "note conflicting type here"),
-                    };
-                    let mut err = struct_span_err!(self.resolver.session,
-                                                   import_span,
-                                                   E0256,
-                                                   "import `{}` conflicts with {}",
-                                                   name,
-                                                   what);
-                    if let Some(span) = name_binding.span {
-                        err.span_note(span, note);
-                    }
-                    err.emit();
-                }
-                Some(_) | None => {}
-            }
+    fn report_conflict(&mut self,
+                       name: Name,
+                       ns: Namespace,
+                       binding: &'b NameBinding<'b>,
+                       old_binding: &'b NameBinding<'b>) {
+        if old_binding.is_extern_crate() {
+            let msg = format!("import `{0}` conflicts with imported crate \
+                               in this module (maybe you meant `use {0}::*`?)",
+                              name);
+            span_err!(self.resolver.session, binding.span.unwrap(), E0254, "{}", &msg);
+        } else if old_binding.is_import() {
+            let ns_word = match (ns, old_binding.module()) {
+                (ValueNS, _) => "value",
+                (TypeNS, Some(module)) if module.is_normal() => "module",
+                (TypeNS, Some(module)) if module.is_trait() => "trait",
+                (TypeNS, _) => "type",
+            };
+            let mut err = struct_span_err!(self.resolver.session,
+                                           binding.span.unwrap(),
+                                           E0252,
+                                           "a {} named `{}` has already been imported \
+                                            in this module",
+                                           ns_word,
+                                           name);
+            err.span_note(old_binding.span.unwrap(),
+                          &format!("previous import of `{}` here", name));
+            err.emit();
+        } else if ns == ValueNS { // Check for item conflicts in the value namespace
+            let mut err = struct_span_err!(self.resolver.session,
+                                           binding.span.unwrap(),
+                                           E0255,
+                                           "import `{}` conflicts with value in this module",
+                                           name);
+            err.span_note(old_binding.span.unwrap(), "conflicting value here");
+            err.emit();
+        } else { // Check for item conflicts in the type namespace
+            let (what, note) = match old_binding.module() {
+                Some(ref module) if module.is_normal() =>
+                    ("existing submodule", "note conflicting module here"),
+                Some(ref module) if module.is_trait() =>
+                    ("trait in this module", "note conflicting trait here"),
+                _ => ("type in this module", "note conflicting type here"),
+            };
+            let mut err = struct_span_err!(self.resolver.session,
+                                           binding.span.unwrap(),
+                                           E0256,
+                                           "import `{}` conflicts with {}",
+                                           name,
+                                           what);
+            err.span_note(old_binding.span.unwrap(), note);
+            err.emit();
         }
     }
 }
diff --git a/src/test/compile-fail/double-type-import.rs b/src/test/compile-fail/double-type-import.rs
index d6d7dbb4aec..923f95e69d1 100644
--- a/src/test/compile-fail/double-type-import.rs
+++ b/src/test/compile-fail/double-type-import.rs
@@ -20,5 +20,5 @@ mod foo {
 }
 
 fn main() {
-    let _ = foo::X; //~ ERROR unresolved name `foo::X`
+    let _ = foo::X;
 }
diff --git a/src/test/compile-fail/unresolved-import.rs b/src/test/compile-fail/unresolved-import.rs
index b6207450d98..b60d19fcab4 100644
--- a/src/test/compile-fail/unresolved-import.rs
+++ b/src/test/compile-fail/unresolved-import.rs
@@ -14,9 +14,9 @@ use foo::bar; //~ ERROR unresolved import `foo::bar`. Maybe a missing `extern cr
 
 use bar::Baz as x; //~ ERROR unresolved import `bar::Baz`. There is no `Baz` in `bar`. Did you mean to use `Bar`?
 
-use food::baz; //~ ERROR unresolved import `food::baz`. There is no `baz` in `food`. Did you mean to use the re-exported import `bag`?
+use food::baz; //~ ERROR unresolved import `food::baz`. There is no `baz` in `food`. Did you mean to use `bag`?
 
-use food::{beens as Foo}; //~ ERROR unresolved import `food::beens`. There is no `beens` in `food`. Did you mean to use the re-exported import `beans`?
+use food::{beens as Foo}; //~ ERROR unresolved import `food::beens`. There is no `beens` in `food`. Did you mean to use `beans`?
 
 mod bar {
     pub struct Bar;