]> git.lizzy.rs Git - rust.git/commitdiff
resolve: factor out resolve imports to its own module
authorNick Cameron <ncameron@mozilla.com>
Sun, 15 Mar 2015 21:44:19 +0000 (10:44 +1300)
committerNick Cameron <ncameron@mozilla.com>
Sun, 15 Mar 2015 22:03:54 +0000 (11:03 +1300)
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/record_exports.rs
src/librustc_resolve/resolve_imports.rs [new file with mode: 0644]

index 5f7a0e63337f476ec46bbaf53411c506395871ca..0282484ba285e2ab69e0b9fcbbac4a820d644543 100644 (file)
 //! any imports resolved.
 
 use {DefModifiers, PUBLIC, IMPORTABLE};
-use ImportDirective;
-use ImportDirectiveSubclass::{self, SingleImport, GlobImport};
-use ImportResolution;
+use resolve_imports::ImportDirective;
+use resolve_imports::ImportDirectiveSubclass::{self, SingleImport, GlobImport};
+use resolve_imports::ImportResolution;
 use Module;
 use ModuleKind::*;
 use Namespace::{TypeNS, ValueNS};
 use NameBindings;
+use {names_to_string, module_to_string};
 use ParentLink::{self, ModuleParentLink, BlockParentLink};
 use Resolver;
-use Shadowable;
+use resolve_imports::Shadowable;
 use TypeNsDef;
 
 use self::DuplicateCheckingMode::*;
@@ -381,7 +382,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                                                               false,
                                                               true));
                     debug!("(build reduced graph for item) found extern `{}`",
-                            self.module_to_string(&*external_module));
+                            module_to_string(&*external_module));
                     self.check_for_conflicts_between_external_crates(&**parent, name, sp);
                     parent.external_module_children.borrow_mut()
                           .insert(name, external_module.clone());
@@ -836,7 +837,7 @@ fn build_reduced_graph_for_external_crate_def(&mut self,
     /// Builds the reduced graph rooted at the given external module.
     fn populate_external_module(&mut self, module: &Rc<Module>) {
         debug!("(populating external module) attempting to populate {}",
-               self.module_to_string(&**module));
+               module_to_string(&**module));
 
         let def_id = match module.def_id.get() {
             None => {
@@ -903,7 +904,7 @@ fn build_import_directive(&mut self,
         match subclass {
             SingleImport(target, _) => {
                 debug!("(building import directive) building import directive: {}::{}",
-                       self.names_to_string(&module_.imports.borrow().last().unwrap().module_path),
+                       names_to_string(&module_.imports.borrow().last().unwrap().module_path),
                        token::get_name(target));
 
                 let mut import_resolutions = module_.import_resolutions.borrow_mut();
index cf974024e8b554248786aaf1a07831329dac2b6b..67e9f71551a22ed57a556a2b24c201cefa4f0904 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -38,7 +38,6 @@
 use self::Namespace::*;
 use self::NamespaceResult::*;
 use self::NameDefinition::*;
-use self::ImportDirectiveSubclass::*;
 use self::ResolveResult::*;
 use self::FallbackSuggestion::*;
 use self::TypeParameters::*;
 use std::rc::{Rc, Weak};
 use std::usize;
 
+use resolve_imports::{Target, ImportDirective, ImportResolution};
+use resolve_imports::Shadowable;
+
+
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
 pub mod diagnostics;
 mod check_unused;
 mod record_exports;
 mod build_reduced_graph;
+mod resolve_imports;
 
 #[derive(Copy)]
 struct BindingInfo {
@@ -253,13 +257,6 @@ fn visit_fn(&mut self,
     }
 }
 
-/// Contains data for specific types of import directives.
-#[derive(Copy,Debug)]
-enum ImportDirectiveSubclass {
-    SingleImport(Name /* target */, Name /* source */),
-    GlobImport
-}
-
 type ErrorMessage = Option<(Span, String)>;
 
 enum ResolveResult<T> {
@@ -366,146 +363,6 @@ fn new(kind: RibKind) -> Rib {
     }
 }
 
-/// Whether an import can be shadowed by another import.
-#[derive(Debug,PartialEq,Clone,Copy)]
-enum Shadowable {
-    Always,
-    Never
-}
-
-/// One import directive.
-#[derive(Debug)]
-struct ImportDirective {
-    module_path: Vec<Name>,
-    subclass: ImportDirectiveSubclass,
-    span: Span,
-    id: NodeId,
-    is_public: bool, // see note in ImportResolution about how to use this
-    shadowable: Shadowable,
-}
-
-impl ImportDirective {
-    fn new(module_path: Vec<Name> ,
-           subclass: ImportDirectiveSubclass,
-           span: Span,
-           id: NodeId,
-           is_public: bool,
-           shadowable: Shadowable)
-           -> ImportDirective {
-        ImportDirective {
-            module_path: module_path,
-            subclass: subclass,
-            span: span,
-            id: id,
-            is_public: is_public,
-            shadowable: shadowable,
-        }
-    }
-}
-
-/// The item that an import resolves to.
-#[derive(Clone,Debug)]
-struct Target {
-    target_module: Rc<Module>,
-    bindings: Rc<NameBindings>,
-    shadowable: Shadowable,
-}
-
-impl Target {
-    fn new(target_module: Rc<Module>,
-           bindings: Rc<NameBindings>,
-           shadowable: Shadowable)
-           -> Target {
-        Target {
-            target_module: target_module,
-            bindings: bindings,
-            shadowable: shadowable,
-        }
-    }
-}
-
-/// An ImportResolution represents a particular `use` directive.
-#[derive(Debug)]
-struct ImportResolution {
-    /// Whether this resolution came from a `use` or a `pub use`. Note that this
-    /// should *not* be used whenever resolution is being performed. Privacy
-    /// testing occurs during a later phase of compilation.
-    is_public: bool,
-
-    // The number of outstanding references to this name. When this reaches
-    // zero, outside modules can count on the targets being correct. Before
-    // then, all bets are off; future imports could override this name.
-    // Note that this is usually either 0 or 1 - shadowing is forbidden the only
-    // way outstanding_references is > 1 in a legal program is if the name is
-    // used in both namespaces.
-    outstanding_references: uint,
-
-    /// The value that this `use` directive names, if there is one.
-    value_target: Option<Target>,
-    /// The source node of the `use` directive leading to the value target
-    /// being non-none
-    value_id: NodeId,
-
-    /// The type that this `use` directive names, if there is one.
-    type_target: Option<Target>,
-    /// The source node of the `use` directive leading to the type target
-    /// being non-none
-    type_id: NodeId,
-}
-
-impl ImportResolution {
-    fn new(id: NodeId, is_public: bool) -> ImportResolution {
-        ImportResolution {
-            type_id: id,
-            value_id: id,
-            outstanding_references: 0,
-            value_target: None,
-            type_target: None,
-            is_public: is_public,
-        }
-    }
-
-    fn target_for_namespace(&self, namespace: Namespace)
-                                -> Option<Target> {
-        match namespace {
-            TypeNS  => self.type_target.clone(),
-            ValueNS => self.value_target.clone(),
-        }
-    }
-
-    fn id(&self, namespace: Namespace) -> NodeId {
-        match namespace {
-            TypeNS  => self.type_id,
-            ValueNS => self.value_id,
-        }
-    }
-
-    fn shadowable(&self, namespace: Namespace) -> Shadowable {
-        let target = self.target_for_namespace(namespace);
-        if target.is_none() {
-            return Shadowable::Always;
-        }
-
-        target.unwrap().shadowable
-    }
-
-    fn set_target_and_id(&mut self,
-                         namespace: Namespace,
-                         target: Option<Target>,
-                         id: NodeId) {
-        match namespace {
-            TypeNS  => {
-                self.type_target = target;
-                self.type_id = id;
-            }
-            ValueNS => {
-                self.value_target = target;
-                self.value_id = id;
-            }
-        }
-    }
-}
-
 /// The link from a module up to its nearest parent node.
 #[derive(Clone,Debug)]
 enum ParentLink {
@@ -978,7 +835,6 @@ enum FallbackChecks {
     OnlyTraitAndStatics
 }
 
-
 impl<'a, 'tcx> Resolver<'a, 'tcx> {
     fn new(session: &'a Session,
            ast_map: &'a ast_map::Map<'tcx>,
@@ -1038,151 +894,6 @@ fn new(session: &'a Session,
         }
     }
 
-    // Import resolution
-    //
-    // This is a fixed-point algorithm. We resolve imports until our efforts
-    // are stymied by an unresolved import; then we bail out of the current
-    // module and continue. We terminate successfully once no more imports
-    // remain or unsuccessfully when no forward progress in resolving imports
-    // is made.
-
-    /// Resolves all imports for the crate. This method performs the fixed-
-    /// point iteration.
-    fn resolve_imports(&mut self) {
-        let mut i = 0;
-        let mut prev_unresolved_imports = 0;
-        loop {
-            debug!("(resolving imports) iteration {}, {} imports left",
-                   i, self.unresolved_imports);
-
-            let module_root = self.graph_root.get_module();
-            self.resolve_imports_for_module_subtree(module_root.clone());
-
-            if self.unresolved_imports == 0 {
-                debug!("(resolving imports) success");
-                break;
-            }
-
-            if self.unresolved_imports == prev_unresolved_imports {
-                self.report_unresolved_imports(module_root);
-                break;
-            }
-
-            i += 1;
-            prev_unresolved_imports = self.unresolved_imports;
-        }
-    }
-
-    /// Attempts to resolve imports for the given module and all of its
-    /// submodules.
-    fn resolve_imports_for_module_subtree(&mut self, module_: Rc<Module>) {
-        debug!("(resolving imports for module subtree) resolving {}",
-               self.module_to_string(&*module_));
-        let orig_module = replace(&mut self.current_module, module_.clone());
-        self.resolve_imports_for_module(module_.clone());
-        self.current_module = orig_module;
-
-        build_reduced_graph::populate_module_if_necessary(self, &module_);
-        for (_, child_node) in &*module_.children.borrow() {
-            match child_node.get_module_if_available() {
-                None => {
-                    // Nothing to do.
-                }
-                Some(child_module) => {
-                    self.resolve_imports_for_module_subtree(child_module);
-                }
-            }
-        }
-
-        for (_, child_module) in &*module_.anonymous_children.borrow() {
-            self.resolve_imports_for_module_subtree(child_module.clone());
-        }
-    }
-
-    /// Attempts to resolve imports for the given module only.
-    fn resolve_imports_for_module(&mut self, module: Rc<Module>) {
-        if module.all_imports_resolved() {
-            debug!("(resolving imports for module) all imports resolved for \
-                   {}",
-                   self.module_to_string(&*module));
-            return;
-        }
-
-        let imports = module.imports.borrow();
-        let import_count = imports.len();
-        while module.resolved_import_count.get() < import_count {
-            let import_index = module.resolved_import_count.get();
-            let import_directive = &(*imports)[import_index];
-            match self.resolve_import_for_module(module.clone(),
-                                                 import_directive) {
-                Failed(err) => {
-                    let (span, help) = match err {
-                        Some((span, msg)) => (span, format!(". {}", msg)),
-                        None => (import_directive.span, String::new())
-                    };
-                    let msg = format!("unresolved import `{}`{}",
-                                      self.import_path_to_string(
-                                          &import_directive.module_path,
-                                          import_directive.subclass),
-                                      help);
-                    self.resolve_error(span, &msg[..]);
-                }
-                Indeterminate => break, // Bail out. We'll come around next time.
-                Success(()) => () // Good. Continue.
-            }
-
-            module.resolved_import_count
-                  .set(module.resolved_import_count.get() + 1);
-        }
-    }
-
-    fn names_to_string(&self, names: &[Name]) -> String {
-        let mut first = true;
-        let mut result = String::new();
-        for name in names {
-            if first {
-                first = false
-            } else {
-                result.push_str("::")
-            }
-            result.push_str(&token::get_name(*name));
-        };
-        result
-    }
-
-    fn path_names_to_string(&self, path: &Path, depth: usize) -> String {
-        let names: Vec<ast::Name> = path.segments[..path.segments.len()-depth]
-                                        .iter()
-                                        .map(|seg| seg.identifier.name)
-                                        .collect();
-        self.names_to_string(&names[..])
-    }
-
-    fn import_directive_subclass_to_string(&mut self,
-                                           subclass: ImportDirectiveSubclass)
-                                           -> String {
-        match subclass {
-            SingleImport(_, source) => {
-                token::get_name(source).to_string()
-            }
-            GlobImport => "*".to_string()
-        }
-    }
-
-    fn import_path_to_string(&mut self,
-                             names: &[Name],
-                             subclass: ImportDirectiveSubclass)
-                             -> String {
-        if names.is_empty() {
-            self.import_directive_subclass_to_string(subclass)
-        } else {
-            (format!("{}::{}",
-                     self.names_to_string(names),
-                     self.import_directive_subclass_to_string(
-                         subclass))).to_string()
-        }
-    }
-
     #[inline]
     fn record_import_use(&mut self, import_id: NodeId, name: Name) {
         if !self.make_glob_map {
@@ -1206,102 +917,6 @@ fn get_trait_name(&self, did: DefId) -> Name {
         }
     }
 
-    /// Attempts to resolve the given import. The return value indicates
-    /// failure if we're certain the name does not exist, indeterminate if we
-    /// don't know whether the name exists at the moment due to other
-    /// currently-unresolved imports, or success if we know the name exists.
-    /// If successful, the resolved bindings are written into the module.
-    fn resolve_import_for_module(&mut self,
-                                 module_: Rc<Module>,
-                                 import_directive: &ImportDirective)
-                                 -> ResolveResult<()> {
-        let mut resolution_result = Failed(None);
-        let module_path = &import_directive.module_path;
-
-        debug!("(resolving import for module) resolving import `{}::...` in `{}`",
-               self.names_to_string(&module_path[..]),
-               self.module_to_string(&*module_));
-
-        // First, resolve the module path for the directive, if necessary.
-        let container = if module_path.len() == 0 {
-            // Use the crate root.
-            Some((self.graph_root.get_module(), LastMod(AllPublic)))
-        } else {
-            match self.resolve_module_path(module_.clone(),
-                                           &module_path[..],
-                                           DontUseLexicalScope,
-                                           import_directive.span,
-                                           ImportSearch) {
-                Failed(err) => {
-                    resolution_result = Failed(err);
-                    None
-                },
-                Indeterminate => {
-                    resolution_result = Indeterminate;
-                    None
-                }
-                Success(container) => Some(container),
-            }
-        };
-
-        match container {
-            None => {}
-            Some((containing_module, lp)) => {
-                // We found the module that the target is contained
-                // within. Attempt to resolve the import within it.
-
-                match import_directive.subclass {
-                    SingleImport(target, source) => {
-                        resolution_result =
-                            self.resolve_single_import(&module_,
-                                                       containing_module,
-                                                       target,
-                                                       source,
-                                                       import_directive,
-                                                       lp);
-                    }
-                    GlobImport => {
-                        resolution_result =
-                            self.resolve_glob_import(&module_,
-                                                     containing_module,
-                                                     import_directive,
-                                                     lp);
-                    }
-                }
-            }
-        }
-
-        // Decrement the count of unresolved imports.
-        match resolution_result {
-            Success(()) => {
-                assert!(self.unresolved_imports >= 1);
-                self.unresolved_imports -= 1;
-            }
-            _ => {
-                // Nothing to do here; just return the error.
-            }
-        }
-
-        // Decrement the count of unresolved globs if necessary. But only if
-        // the resolution result is indeterminate -- otherwise we'll stop
-        // processing imports here. (See the loop in
-        // resolve_imports_for_module).
-
-        if !resolution_result.indeterminate() {
-            match import_directive.subclass {
-                GlobImport => {
-                    assert!(module_.glob_count.get() >= 1);
-                    module_.glob_count.set(module_.glob_count.get() - 1);
-                }
-                SingleImport(..) => {
-                    // Ignore.
-                }
-            }
-        }
-
-        return resolution_result;
-    }
-
     fn create_name_bindings_from_module(module: Rc<Module>) -> NameBindings {
         NameBindings {
             type_def: RefCell::new(Some(TypeNsDef {
@@ -1314,612 +929,6 @@ fn create_name_bindings_from_module(module: Rc<Module>) -> NameBindings {
         }
     }
 
-    fn resolve_single_import(&mut self,
-                             module_: &Module,
-                             target_module: Rc<Module>,
-                             target: Name,
-                             source: Name,
-                             directive: &ImportDirective,
-                             lp: LastPrivate)
-                             -> ResolveResult<()> {
-        debug!("(resolving single import) resolving `{}` = `{}::{}` from \
-                `{}` id {}, last private {:?}",
-               token::get_name(target),
-               self.module_to_string(&*target_module),
-               token::get_name(source),
-               self.module_to_string(module_),
-               directive.id,
-               lp);
-
-        let lp = match lp {
-            LastMod(lp) => lp,
-            LastImport {..} => {
-                self.session
-                    .span_bug(directive.span,
-                              "not expecting Import here, must be LastMod")
-            }
-        };
-
-        // We need to resolve both namespaces for this to succeed.
-        //
-
-        let mut value_result = UnknownResult;
-        let mut type_result = UnknownResult;
-
-        // Search for direct children of the containing module.
-        build_reduced_graph::populate_module_if_necessary(self, &target_module);
-
-        match target_module.children.borrow().get(&source) {
-            None => {
-                // Continue.
-            }
-            Some(ref child_name_bindings) => {
-                // pub_err makes sure we don't give the same error twice.
-                let mut pub_err = false;
-                if child_name_bindings.defined_in_namespace(ValueNS) {
-                    debug!("(resolving single import) found value binding");
-                    value_result = BoundResult(target_module.clone(),
-                                               (*child_name_bindings).clone());
-                    if directive.is_public && !child_name_bindings.is_public(ValueNS) {
-                        let msg = format!("`{}` is private", token::get_name(source));
-                        span_err!(self.session, directive.span, E0364, "{}", &msg);
-                        pub_err = true;
-                    }
-                }
-                if child_name_bindings.defined_in_namespace(TypeNS) {
-                    debug!("(resolving single import) found type binding");
-                    type_result = BoundResult(target_module.clone(),
-                                              (*child_name_bindings).clone());
-                    if !pub_err && directive.is_public && !child_name_bindings.is_public(TypeNS) {
-                        let msg = format!("`{}` is private", token::get_name(source));
-                        span_err!(self.session, directive.span, E0365, "{}", &msg);
-                    }
-                }
-            }
-        }
-
-        // Unless we managed to find a result in both namespaces (unlikely),
-        // search imports as well.
-        let mut value_used_reexport = false;
-        let mut type_used_reexport = false;
-        match (value_result.clone(), type_result.clone()) {
-            (BoundResult(..), BoundResult(..)) => {} // Continue.
-            _ => {
-                // 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 this import.
-
-                if target_module.glob_count.get() > 0 {
-                    debug!("(resolving single import) unresolved glob; \
-                            bailing out");
-                    return Indeterminate;
-                }
-
-                // Now search the exported imports within the containing module.
-                match target_module.import_resolutions.borrow().get(&source) {
-                    None => {
-                        debug!("(resolving single import) no import");
-                        // The containing module definitely doesn't have an
-                        // exported import with the name in question. We can
-                        // therefore accurately report that the names are
-                        // unbound.
-
-                        if value_result.is_unknown() {
-                            value_result = UnboundResult;
-                        }
-                        if type_result.is_unknown() {
-                            type_result = UnboundResult;
-                        }
-                    }
-                    Some(import_resolution)
-                            if import_resolution.outstanding_references == 0 => {
-
-                        fn get_binding(this: &mut Resolver,
-                                       import_resolution: &ImportResolution,
-                                       namespace: Namespace,
-                                       source: &Name)
-                                    -> NamespaceResult {
-
-                            // Import resolutions must be declared with "pub"
-                            // in order to be exported.
-                            if !import_resolution.is_public {
-                                return UnboundResult;
-                            }
-
-                            match import_resolution.target_for_namespace(namespace) {
-                                None => {
-                                    return UnboundResult;
-                                }
-                                Some(Target {
-                                    target_module,
-                                    bindings,
-                                    shadowable: _
-                                }) => {
-                                    debug!("(resolving single import) found \
-                                            import in ns {:?}", namespace);
-                                    let id = import_resolution.id(namespace);
-                                    // track used imports and extern crates as well
-                                    this.used_imports.insert((id, namespace));
-                                    this.record_import_use(id, *source);
-                                    match target_module.def_id.get() {
-                                        Some(DefId{krate: kid, ..}) => {
-                                            this.used_crates.insert(kid);
-                                        },
-                                        _ => {}
-                                    }
-                                    return BoundResult(target_module, bindings);
-                                }
-                            }
-                        }
-
-                        // The name is an import which has been fully
-                        // resolved. We can, therefore, just follow it.
-                        if value_result.is_unknown() {
-                            value_result = get_binding(self,
-                                                       import_resolution,
-                                                       ValueNS,
-                                                       &source);
-                            value_used_reexport = import_resolution.is_public;
-                        }
-                        if type_result.is_unknown() {
-                            type_result = get_binding(self,
-                                                      import_resolution,
-                                                      TypeNS,
-                                                      &source);
-                            type_used_reexport = import_resolution.is_public;
-                        }
-
-                    }
-                    Some(_) => {
-                        // If target_module is the same module whose import we are resolving
-                        // and there it has an unresolved import with the same name as `source`,
-                        // 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 the
-                        // check_for_conflicts_between_imports_and_items call below handle
-                        // the conflict
-                        match (module_.def_id.get(),  target_module.def_id.get()) {
-                            (Some(id1), Some(id2)) if id1 == id2  => {
-                                if value_result.is_unknown() {
-                                    value_result = UnboundResult;
-                                }
-                                if type_result.is_unknown() {
-                                    type_result = UnboundResult;
-                                }
-                            }
-                            _ =>  {
-                                // The import is unresolved. Bail out.
-                                debug!("(resolving single import) unresolved import; \
-                                        bailing out");
-                                return Indeterminate;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        let mut value_used_public = false;
-        let mut type_used_public = false;
-
-        // If we didn't find a result in the type namespace, search the
-        // external modules.
-        match type_result {
-            BoundResult(..) => {}
-            _ => {
-                match target_module.external_module_children.borrow_mut().get(&source).cloned() {
-                    None => {} // Continue.
-                    Some(module) => {
-                        debug!("(resolving single import) found external module");
-                        // track the module as used.
-                        match module.def_id.get() {
-                            Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
-                            _ => {}
-                        }
-                        let name_bindings =
-                            Rc::new(Resolver::create_name_bindings_from_module(module));
-                        type_result = BoundResult(target_module.clone(), name_bindings);
-                        type_used_public = true;
-                    }
-                }
-            }
-        }
-
-        // We've successfully resolved the import. Write the results in.
-        let mut import_resolutions = module_.import_resolutions.borrow_mut();
-        let import_resolution = &mut (*import_resolutions)[target];
-
-        {
-            let mut check_and_write_import = |namespace, result: &_, used_public: &mut bool| {
-                let namespace_name = match namespace {
-                    TypeNS => "type",
-                    ValueNS => "value",
-                };
-
-                match *result {
-                    BoundResult(ref target_module, ref name_bindings) => {
-                        debug!("(resolving single import) found {:?} target: {:?}",
-                               namespace_name,
-                               name_bindings.def_for_namespace(namespace));
-                        self.check_for_conflicting_import(
-                            &import_resolution.target_for_namespace(namespace),
-                            directive.span,
-                            target,
-                            namespace);
-
-                        self.check_that_import_is_importable(
-                            &**name_bindings,
-                            directive.span,
-                            target,
-                            namespace);
-
-                        let target = Some(Target::new(target_module.clone(),
-                                                      name_bindings.clone(),
-                                                      directive.shadowable));
-                        import_resolution.set_target_and_id(namespace, target, directive.id);
-                        import_resolution.is_public = directive.is_public;
-                        *used_public = name_bindings.defined_in_public_namespace(namespace);
-                    }
-                    UnboundResult => { /* Continue. */ }
-                    UnknownResult => {
-                        panic!("{:?} result should be known at this point", namespace_name);
-                    }
-                }
-            };
-            check_and_write_import(ValueNS, &value_result, &mut value_used_public);
-            check_and_write_import(TypeNS, &type_result, &mut type_used_public);
-        }
-
-        self.check_for_conflicts_between_imports_and_items(
-            module_,
-            import_resolution,
-            directive.span,
-            target);
-
-        if value_result.is_unbound() && type_result.is_unbound() {
-            let msg = format!("There is no `{}` in `{}`",
-                              token::get_name(source),
-                              self.module_to_string(&target_module));
-            return Failed(Some((directive.span, msg)));
-        }
-        let value_used_public = value_used_reexport || value_used_public;
-        let type_used_public = type_used_reexport || type_used_public;
-
-        assert!(import_resolution.outstanding_references >= 1);
-        import_resolution.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.
-        let value_def_and_priv = import_resolution.value_target.as_ref().map(|target| {
-            let def = target.bindings.def_for_namespace(ValueNS).unwrap();
-            (def, if value_used_public { lp } else { DependsOn(def.def_id()) })
-        });
-        let type_def_and_priv = import_resolution.type_target.as_ref().map(|target| {
-            let def = target.bindings.def_for_namespace(TypeNS).unwrap();
-            (def, if type_used_public { lp } else { DependsOn(def.def_id()) })
-        });
-
-        let import_lp = LastImport {
-            value_priv: value_def_and_priv.map(|(_, p)| p),
-            value_used: Used,
-            type_priv: type_def_and_priv.map(|(_, p)| p),
-            type_used: Used
-        };
-
-        if let Some((def, _)) = value_def_and_priv {
-            self.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.def_map.borrow_mut().insert(directive.id, PathResolution {
-                base_def: def,
-                last_private: import_lp,
-                depth: 0
-            });
-        }
-
-        debug!("(resolving single import) successfully resolved import");
-        return Success(());
-    }
-
-    // Resolves a glob import. Note that this function cannot fail; it either
-    // succeeds or bails out (as importing * from an empty module or a module
-    // that exports nothing is valid). target_module is the module we are
-    // actually importing, i.e., `foo` in `use foo::*`.
-    fn resolve_glob_import(&mut self,
-                           module_: &Module,
-                           target_module: Rc<Module>,
-                           import_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).all_imports_resolved() {
-            debug!("(resolving glob import) target module has unresolved \
-                    imports; bailing out");
-            return Indeterminate;
-        }
-
-        assert_eq!(target_module.glob_count.get(), 0);
-
-        // Add all resolved imports from the containing module.
-        let import_resolutions = target_module.import_resolutions.borrow();
-        for (ident, target_import_resolution) in &*import_resolutions {
-            debug!("(resolving glob import) writing module resolution \
-                    {} into `{}`",
-                   token::get_name(*ident),
-                   self.module_to_string(module_));
-
-            if !target_import_resolution.is_public {
-                debug!("(resolving glob import) nevermind, just kidding");
-                continue
-            }
-
-            // Here we merge two import resolutions.
-            let mut import_resolutions = module_.import_resolutions.borrow_mut();
-            match import_resolutions.get_mut(ident) {
-                Some(dest_import_resolution) => {
-                    // Merge the two import resolutions at a finer-grained
-                    // level.
-
-                    match target_import_resolution.value_target {
-                        None => {
-                            // Continue.
-                        }
-                        Some(ref value_target) => {
-                            self.check_for_conflicting_import(&dest_import_resolution.value_target,
-                                                              import_directive.span,
-                                                              *ident,
-                                                              ValueNS);
-                            dest_import_resolution.value_target = Some(value_target.clone());
-                        }
-                    }
-                    match target_import_resolution.type_target {
-                        None => {
-                            // Continue.
-                        }
-                        Some(ref type_target) => {
-                            self.check_for_conflicting_import(&dest_import_resolution.type_target,
-                                                              import_directive.span,
-                                                              *ident,
-                                                              TypeNS);
-                            dest_import_resolution.type_target = Some(type_target.clone());
-                        }
-                    }
-                    dest_import_resolution.is_public = is_public;
-                    continue;
-                }
-                None => {}
-            }
-
-            // Simple: just copy the old import resolution.
-            let mut new_import_resolution = ImportResolution::new(id, is_public);
-            new_import_resolution.value_target =
-                target_import_resolution.value_target.clone();
-            new_import_resolution.type_target =
-                target_import_resolution.type_target.clone();
-
-            import_resolutions.insert(*ident, new_import_resolution);
-        }
-
-        // Add all children from the containing module.
-        build_reduced_graph::populate_module_if_necessary(self, &target_module);
-
-        for (&name, name_bindings) in &*target_module.children.borrow() {
-            self.merge_import_resolution(module_,
-                                         target_module.clone(),
-                                         import_directive,
-                                         name,
-                                         name_bindings.clone());
-
-        }
-
-        // Add external module children from the containing module.
-        for (&name, module) in &*target_module.external_module_children.borrow() {
-            let name_bindings =
-                Rc::new(Resolver::create_name_bindings_from_module(module.clone()));
-            self.merge_import_resolution(module_,
-                                         target_module.clone(),
-                                         import_directive,
-                                         name,
-                                         name_bindings);
-        }
-
-        // Record the destination of this import
-        if let Some(did) = target_module.def_id.get() {
-            self.def_map.borrow_mut().insert(id, PathResolution {
-                base_def: DefMod(did),
-                last_private: lp,
-                depth: 0
-            });
-        }
-
-        debug!("(resolving glob import) successfully resolved import");
-        return Success(());
-    }
-
-    fn merge_import_resolution(&mut self,
-                               module_: &Module,
-                               containing_module: Rc<Module>,
-                               import_directive: &ImportDirective,
-                               name: Name,
-                               name_bindings: Rc<NameBindings>) {
-        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).get().unwrap_or_else(
-            |vacant_entry| {
-                // Create a new import resolution from this child.
-                vacant_entry.insert(ImportResolution::new(id, is_public))
-            });
-
-        debug!("(resolving glob import) writing resolution `{}` in `{}` \
-               to `{}`",
-               &token::get_name(name),
-               self.module_to_string(&*containing_module),
-               self.module_to_string(module_));
-
-        // Merge the child item into the import resolution.
-        {
-            let mut merge_child_item = |namespace| {
-                if name_bindings.defined_in_namespace_with(namespace, IMPORTABLE | PUBLIC) {
-                    let namespace_name = match namespace {
-                        TypeNS => "type",
-                        ValueNS => "value",
-                    };
-                    debug!("(resolving glob import) ... for {} target", namespace_name);
-                    if dest_import_resolution.shadowable(namespace) == Shadowable::Never {
-                        let msg = format!("a {} named `{}` has already been imported \
-                                           in this module",
-                                          namespace_name,
-                                          &token::get_name(name));
-                        span_err!(self.session, import_directive.span, E0251, "{}", msg);
-                    } else {
-                        let target = Target::new(containing_module.clone(),
-                                                 name_bindings.clone(),
-                                                 import_directive.shadowable);
-                        dest_import_resolution.set_target_and_id(namespace,
-                                                                 Some(target),
-                                                                 id);
-                    }
-                }
-            };
-            merge_child_item(ValueNS);
-            merge_child_item(TypeNS);
-        }
-
-        dest_import_resolution.is_public = is_public;
-
-        self.check_for_conflicts_between_imports_and_items(
-            module_,
-            dest_import_resolution,
-            import_directive.span,
-            name);
-    }
-
-    /// Checks that imported names and items don't have the same name.
-    fn check_for_conflicting_import(&mut self,
-                                    target: &Option<Target>,
-                                    import_span: Span,
-                                    name: Name,
-                                    namespace: Namespace) {
-        debug!("check_for_conflicting_import: {}; target exists: {}",
-               &token::get_name(name),
-               target.is_some());
-
-        match *target {
-            Some(ref target) if target.shadowable != Shadowable::Always => {
-                let msg = format!("a {} named `{}` has already been imported \
-                                   in this module",
-                                  match namespace {
-                                    TypeNS => "type",
-                                    ValueNS => "value",
-                                  },
-                                  &token::get_name(name));
-                span_err!(self.session, import_span, E0252, "{}", &msg[..]);
-            }
-            Some(_) | None => {}
-        }
-    }
-
-    /// Checks that an import is actually importable
-    fn check_that_import_is_importable(&mut self,
-                                       name_bindings: &NameBindings,
-                                       import_span: Span,
-                                       name: Name,
-                                       namespace: Namespace) {
-        if !name_bindings.defined_in_namespace_with(namespace, IMPORTABLE) {
-            let msg = format!("`{}` is not directly importable",
-                              token::get_name(name));
-            span_err!(self.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,
-                                                     import_resolution:
-                                                     &ImportResolution,
-                                                     import_span: Span,
-                                                     name: Name) {
-        // First, check for conflicts between imports and `extern crate`s.
-        if module.external_module_children
-                 .borrow()
-                 .contains_key(&name) {
-            match import_resolution.type_target {
-                Some(ref target) if target.shadowable != Shadowable::Always => {
-                    let msg = format!("import `{0}` conflicts with imported \
-                                       crate in this module \
-                                       (maybe you meant `use {0}::*`?)",
-                                      &token::get_name(name));
-                    span_err!(self.session, import_span, E0254, "{}", &msg[..]);
-                }
-                Some(_) | None => {}
-            }
-        }
-
-        // Check for item conflicts.
-        let children = module.children.borrow();
-        let name_bindings = match children.get(&name) {
-            None => {
-                // There can't be any conflicts.
-                return
-            }
-            Some(ref name_bindings) => (*name_bindings).clone(),
-        };
-
-        match import_resolution.value_target {
-            Some(ref target) if target.shadowable != Shadowable::Always => {
-                if let Some(ref value) = *name_bindings.value_def.borrow() {
-                    span_err!(self.session, import_span, E0255,
-                              "import `{}` conflicts with value in this module",
-                              &token::get_name(name));
-                    if let Some(span) = value.value_span {
-                        self.session.span_note(span, "conflicting value here");
-                    }
-                }
-            }
-            Some(_) | None => {}
-        }
-
-        match import_resolution.type_target {
-            Some(ref target) if target.shadowable != Shadowable::Always => {
-                if let Some(ref ty) = *name_bindings.type_def.borrow() {
-                    let (what, note) = if ty.module_def.is_some() {
-                        ("existing submodule", "note conflicting module here")
-                    } else {
-                        ("type in this module", "note conflicting type here")
-                    };
-                    span_err!(self.session, import_span, E0256,
-                              "import `{}` conflicts with {}",
-                              &token::get_name(name), what);
-                    if let Some(span) = ty.type_span {
-                        self.session.span_note(span, note);
-                    }
-                }
-            }
-            Some(_) | None => {}
-        }
-    }
-
     /// Checks that the names of external crates don't collide with other
     /// external crates.
     fn check_for_conflicts_between_external_crates(&self,
@@ -1987,7 +996,7 @@ fn search_parent_externals(needle: Name, module: &Rc<Module>)
                                               false) {
                 Failed(None) => {
                     let segment_name = token::get_name(name);
-                    let module_name = self.module_to_string(&*search_module);
+                    let module_name = module_to_string(&*search_module);
                     let mut span = span;
                     let msg = if "???" == &module_name[..] {
                         span.hi = span.lo + Pos::from_usize(segment_name.len());
@@ -1995,10 +1004,10 @@ fn search_parent_externals(needle: Name, module: &Rc<Module>)
                         match search_parent_externals(name,
                                                      &self.current_module) {
                             Some(module) => {
-                                let path_str = self.names_to_string(module_path);
-                                let target_mod_str = self.module_to_string(&*module);
+                                let path_str = names_to_string(module_path);
+                                let target_mod_str = module_to_string(&*module);
                                 let current_mod_str =
-                                    self.module_to_string(&*self.current_module);
+                                    module_to_string(&*self.current_module);
 
                                 let prefix = if target_mod_str == current_mod_str {
                                     "self::".to_string()
@@ -2089,8 +1098,8 @@ fn resolve_module_path(&mut self,
         assert!(module_path_len > 0);
 
         debug!("(resolving module path for import) processing `{}` rooted at `{}`",
-               self.names_to_string(module_path),
-               self.module_to_string(&*module_));
+               names_to_string(module_path),
+               module_to_string(&*module_));
 
         // Resolve the module prefix, if any.
         let module_prefix_result = self.resolve_module_prefix(module_.clone(),
@@ -2101,7 +1110,7 @@ fn resolve_module_path(&mut self,
         let last_private;
         match module_prefix_result {
             Failed(None) => {
-                let mpath = self.names_to_string(module_path);
+                let mpath = names_to_string(module_path);
                 let mpath = &mpath[..];
                 match mpath.rfind(':') {
                     Some(idx) => {
@@ -2184,7 +1193,7 @@ fn resolve_item_in_lexical_scope(&mut self,
                 namespace {:?} in `{}`",
                token::get_name(name),
                namespace,
-               self.module_to_string(&*module_));
+               module_to_string(&*module_));
 
         // The current module node is handled specially. First, check for
         // its immediate children.
@@ -2421,7 +1430,7 @@ fn resolve_module_prefix(&mut self,
                 break
             }
             debug!("(resolving module prefix) resolving `super` at {}",
-                   self.module_to_string(&*containing_module));
+                   module_to_string(&*containing_module));
             match self.get_nearest_normal_module_parent(containing_module) {
                 None => return Failed(None),
                 Some(new_module) => {
@@ -2432,7 +1441,7 @@ fn resolve_module_prefix(&mut self,
         }
 
         debug!("(resolving module prefix) finished resolving prefix at {}",
-               self.module_to_string(&*containing_module));
+               module_to_string(&*containing_module));
 
         return Success(PrefixFound(containing_module, i));
     }
@@ -2452,7 +1461,7 @@ fn resolve_name_in_module(&mut self,
                               -> ResolveResult<(Target, bool)> {
         debug!("(resolving name in module) resolving `{}` in `{}`",
                &token::get_name(name),
-               self.module_to_string(&*module_));
+               module_to_string(&*module_));
 
         // First, check the direct children of the module.
         build_reduced_graph::populate_module_if_necessary(self, &module_);
@@ -2606,7 +1615,7 @@ fn with_scope<F>(&mut self, name: Option<Name>, f: F) where
                     None => {
                         debug!("!!! (with scope) didn't find `{}` in `{}`",
                                token::get_name(name),
-                               self.module_to_string(&*orig_module));
+                               module_to_string(&*orig_module));
                     }
                     Some(name_bindings) => {
                         match (*name_bindings).get_module_if_available() {
@@ -2614,7 +1623,7 @@ fn with_scope<F>(&mut self, name: Option<Name>, f: F) where
                                 debug!("!!! (with scope) didn't find module \
                                         for `{}` in `{}`",
                                        token::get_name(name),
-                                       self.module_to_string(&*orig_module));
+                                       module_to_string(&*orig_module));
                             }
                             Some(module_) => {
                                 self.current_module = module_;
@@ -2993,7 +2002,7 @@ fn resolve_trait_reference(&mut self,
             } else {
                 self.resolve_error(trait_path.span,
                     &format!("`{}` is not a trait",
-                             self.path_names_to_string(trait_path, path_depth)));
+                             path_names_to_string(trait_path, path_depth)));
 
                 // If it's a typedef, give a note
                 if let DefTy(..) = path_res.base_def {
@@ -3004,7 +2013,7 @@ fn resolve_trait_reference(&mut self,
             }
         } else {
             let msg = format!("use of undeclared trait name `{}`",
-                              self.path_names_to_string(trait_path, path_depth));
+                              path_names_to_string(trait_path, path_depth));
             self.resolve_error(trait_path.span, &msg);
             Err(())
         }
@@ -3120,7 +2129,7 @@ fn check_trait_item(&self, name: Name, span: Span) {
         // If there is a TraitRef in scope for an impl, then the method must be in the trait.
         if let Some((did, ref trait_ref)) = self.current_trait_ref {
             if !self.trait_item_map.contains_key(&(name, did)) {
-                let path_str = self.path_names_to_string(&trait_ref.path, 0);
+                let path_str = path_names_to_string(&trait_ref.path, 0);
                 self.resolve_error(span,
                                     &format!("method `{}` is not a member of trait `{}`",
                                             token::get_name(name),
@@ -3302,7 +2311,7 @@ fn resolve_type(&mut self, ty: &Ty) {
                         // Write the result into the def map.
                         debug!("(resolving type) writing resolution for `{}` \
                                 (id {}) = {:?}",
-                               self.path_names_to_string(path, 0),
+                               path_names_to_string(path, 0),
                                ty.id, def);
                         self.record_def(ty.id, def);
                     }
@@ -3317,7 +2326,7 @@ fn resolve_type(&mut self, ty: &Ty) {
                         };
 
                         let msg = format!("use of undeclared {} `{}`", kind,
-                                          self.path_names_to_string(path, 0));
+                                          path_names_to_string(path, 0));
                         self.resolve_error(ty.span, &msg[..]);
                     }
                 }
@@ -3488,7 +2497,7 @@ struct or enum variant",
                             debug!("(resolving pattern) didn't find struct \
                                     def: {:?}", result);
                             let msg = format!("`{}` does not name a structure",
-                                              self.path_names_to_string(path, 0));
+                                              path_names_to_string(path, 0));
                             self.resolve_error(path.span, &msg[..]);
                         }
                     }
@@ -3741,7 +2750,7 @@ fn resolve_module_relative_path(&mut self,
                     Some((span, msg)) => (span, msg),
                     None => {
                         let msg = format!("Use of undeclared type or module `{}`",
-                                          self.names_to_string(&module_path));
+                                          names_to_string(&module_path));
                         (span, msg)
                     }
                 };
@@ -3801,7 +2810,7 @@ fn resolve_crate_relative_path(&mut self,
                     Some((span, msg)) => (span, msg),
                     None => {
                         let msg = format!("Use of undeclared module `::{}`",
-                                          self.names_to_string(&module_path[..]));
+                                          names_to_string(&module_path[..]));
                         (span, msg)
                     }
                 };
@@ -4021,7 +3030,7 @@ fn is_static_method(this: &Resolver, did: DefId) -> bool {
             if let Some(binding) = module.children.borrow().get(&name) {
                 if let Some(DefMethod(did, _)) = binding.def_for_namespace(ValueNS) {
                     if is_static_method(self, did) {
-                        return StaticMethod(self.path_names_to_string(&path, 0))
+                        return StaticMethod(path_names_to_string(&path, 0))
                     }
                     if self.current_trait_ref.is_some() {
                         return TraitItem;
@@ -4036,7 +3045,7 @@ fn is_static_method(this: &Resolver, did: DefId) -> bool {
         if let Some((trait_did, ref trait_ref)) = self.current_trait_ref {
             if let Some(&did) = self.trait_item_map.get(&(name, trait_did)) {
                 if is_static_method(self, did) {
-                    return TraitMethod(self.path_names_to_string(&trait_ref.path, 0));
+                    return TraitMethod(path_names_to_string(&trait_ref.path, 0));
                 } else {
                     return TraitItem;
                 }
@@ -4128,7 +3137,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                 if let Some(path_res) = resolution {
                     // Check if struct variant
                     if let DefVariant(_, _, true) = path_res.base_def {
-                        let path_name = self.path_names_to_string(path, 0);
+                        let path_name = path_names_to_string(path, 0);
                         self.resolve_error(expr.span,
                                 &format!("`{}` is a struct variant name, but \
                                           this expression \
@@ -4146,7 +3155,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                     } else {
                         // Write the result into the def map.
                         debug!("(resolving expr) resolved `{}`",
-                               self.path_names_to_string(path, 0));
+                               path_names_to_string(path, 0));
 
                         // Partial resolutions will need the set of traits in scope,
                         // so they can be completed during typeck.
@@ -4163,7 +3172,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                     // (The pattern matching def_tys where the id is in self.structs
                     // matches on regular structs while excluding tuple- and enum-like
                     // structs, which wouldn't result in this error.)
-                    let path_name = self.path_names_to_string(path, 0);
+                    let path_name = path_names_to_string(path, 0);
                     let type_res = self.with_no_errors(|this| {
                         this.resolve_path(expr.id, path, 0, TypeNS, false)
                     });
@@ -4250,7 +3259,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                     None => {
                         debug!("(resolving expression) didn't find struct def",);
                         let msg = format!("`{}` does not name a structure",
-                                          self.path_names_to_string(path, 0));
+                                          path_names_to_string(path, 0));
                         self.resolve_error(path.span, &msg[..]);
                     }
                 }
@@ -4440,36 +3449,9 @@ fn enforce_default_binding_mode(&mut self,
     // hit.
     //
 
-    /// A somewhat inefficient routine to obtain the name of a module.
-    fn module_to_string(&self, module: &Module) -> String {
-        let mut names = Vec::new();
-
-        fn collect_mod(names: &mut Vec<ast::Name>, module: &Module) {
-            match module.parent_link {
-                NoParentLink => {}
-                ModuleParentLink(ref module, name) => {
-                    names.push(name);
-                    collect_mod(names, &*module.upgrade().unwrap());
-                }
-                BlockParentLink(ref module, _) => {
-                    // danger, shouldn't be ident?
-                    names.push(special_idents::opaque.name);
-                    collect_mod(names, &*module.upgrade().unwrap());
-                }
-            }
-        }
-        collect_mod(&mut names, module);
-
-        if names.len() == 0 {
-            return "???".to_string();
-        }
-        self.names_to_string(&names.into_iter().rev()
-                                  .collect::<Vec<ast::Name>>())
-    }
-
     #[allow(dead_code)]   // useful for debugging
     fn dump_module(&mut self, module_: Rc<Module>) {
-        debug!("Dump of module `{}`:", self.module_to_string(&*module_));
+        debug!("Dump of module `{}`:", module_to_string(&*module_));
 
         debug!("Children:");
         build_reduced_graph::populate_module_if_necessary(self, &module_);
@@ -4503,6 +3485,56 @@ fn dump_module(&mut self, module_: Rc<Module>) {
     }
 }
 
+
+fn names_to_string(names: &[Name]) -> String {
+    let mut first = true;
+    let mut result = String::new();
+    for name in names {
+        if first {
+            first = false
+        } else {
+            result.push_str("::")
+        }
+        result.push_str(&token::get_name(*name));
+    };
+    result
+}
+
+fn path_names_to_string(path: &Path, depth: usize) -> String {
+    let names: Vec<ast::Name> = path.segments[..path.segments.len()-depth]
+                                    .iter()
+                                    .map(|seg| seg.identifier.name)
+                                    .collect();
+    names_to_string(&names[..])
+}
+
+/// A somewhat inefficient routine to obtain the name of a module.
+fn module_to_string(module: &Module) -> String {
+    let mut names = Vec::new();
+
+    fn collect_mod(names: &mut Vec<ast::Name>, module: &Module) {
+        match module.parent_link {
+            NoParentLink => {}
+            ModuleParentLink(ref module, name) => {
+                names.push(name);
+                collect_mod(names, &*module.upgrade().unwrap());
+            }
+            BlockParentLink(ref module, _) => {
+                // danger, shouldn't be ident?
+                names.push(special_idents::opaque.name);
+                collect_mod(names, &*module.upgrade().unwrap());
+            }
+        }
+    }
+    collect_mod(&mut names, module);
+
+    if names.len() == 0 {
+        return "???".to_string();
+    }
+    names_to_string(&names.into_iter().rev().collect::<Vec<ast::Name>>())
+}
+
+
 pub struct CrateMap {
     pub def_map: DefMap,
     pub freevars: RefCell<FreevarMap>,
@@ -4530,7 +3562,7 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
     build_reduced_graph::build_reduced_graph(&mut resolver, krate);
     session.abort_if_errors();
 
-    resolver.resolve_imports();
+    resolve_imports::resolve_imports(&mut resolver);
     session.abort_if_errors();
 
     record_exports::record(&mut resolver);
index c634035bbf4c4c0dbdbcd9d152bd9ba8f373267e..e953b6398f9c08e6eab61bfc34e807b28c92e740 100644 (file)
@@ -22,6 +22,7 @@
 use Namespace::{self, TypeNS, ValueNS};
 
 use build_reduced_graph;
+use module_to_string;
 
 use rustc::middle::def::Export;
 use syntax::ast;
@@ -60,19 +61,19 @@ fn record_exports_for_module_subtree(&mut self,
                 // OK. Continue.
                 debug!("(recording exports for module subtree) recording \
                         exports for local module `{}`",
-                       self.module_to_string(&*module_));
+                       module_to_string(&*module_));
             }
             None => {
                 // Record exports for the root module.
                 debug!("(recording exports for module subtree) recording \
                         exports for root module `{}`",
-                       self.module_to_string(&*module_));
+                       module_to_string(&*module_));
             }
             Some(_) => {
                 // Bail out.
                 debug!("(recording exports for module subtree) not recording \
                         exports for `{}`",
-                       self.module_to_string(&*module_));
+                       module_to_string(&*module_));
                 return;
             }
         }
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
new file mode 100644 (file)
index 0000000..737ec71
--- /dev/null
@@ -0,0 +1,1021 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use self::ImportDirectiveSubclass::*;
+
+use {PUBLIC, IMPORTABLE};
+use Module;
+use Namespace::{self, TypeNS, ValueNS};
+use NameBindings;
+use NamespaceResult::{BoundResult, UnboundResult, UnknownResult};
+use NamespaceResult;
+use NameSearchType;
+use ResolveResult;
+use Resolver;
+use UseLexicalScopeFlag;
+use {names_to_string, module_to_string};
+
+use build_reduced_graph;
+
+use rustc::middle::def::*;
+use rustc::middle::privacy::*;
+
+use syntax::ast::{DefId, NodeId, Name};
+use syntax::attr::AttrMetaMethods;
+use syntax::parse::token;
+use syntax::codemap::Span;
+
+use std::mem::replace;
+use std::rc::Rc;
+
+
+/// Contains data for specific types of import directives.
+#[derive(Copy,Debug)]
+pub enum ImportDirectiveSubclass {
+    SingleImport(Name /* target */, Name /* source */),
+    GlobImport
+}
+
+/// Whether an import can be shadowed by another import.
+#[derive(Debug,PartialEq,Clone,Copy)]
+pub enum Shadowable {
+    Always,
+    Never
+}
+
+/// One import directive.
+#[derive(Debug)]
+pub struct ImportDirective {
+    pub module_path: Vec<Name>,
+    pub subclass: ImportDirectiveSubclass,
+    pub span: Span,
+    pub id: NodeId,
+    pub is_public: bool, // see note in ImportResolution about how to use this
+    pub shadowable: Shadowable,
+}
+
+impl ImportDirective {
+    pub fn new(module_path: Vec<Name> ,
+           subclass: ImportDirectiveSubclass,
+           span: Span,
+           id: NodeId,
+           is_public: bool,
+           shadowable: Shadowable)
+           -> ImportDirective {
+        ImportDirective {
+            module_path: module_path,
+            subclass: subclass,
+            span: span,
+            id: id,
+            is_public: is_public,
+            shadowable: shadowable,
+        }
+    }
+}
+
+/// The item that an import resolves to.
+#[derive(Clone,Debug)]
+pub struct Target {
+    pub target_module: Rc<Module>,
+    pub bindings: Rc<NameBindings>,
+    pub shadowable: Shadowable,
+}
+
+impl Target {
+    pub fn new(target_module: Rc<Module>,
+           bindings: Rc<NameBindings>,
+           shadowable: Shadowable)
+           -> Target {
+        Target {
+            target_module: target_module,
+            bindings: bindings,
+            shadowable: shadowable,
+        }
+    }
+}
+
+/// An ImportResolution represents a particular `use` directive.
+#[derive(Debug)]
+pub struct ImportResolution {
+    /// Whether this resolution came from a `use` or a `pub use`. Note that this
+    /// should *not* be used whenever resolution is being performed. Privacy
+    /// testing occurs during a later phase of compilation.
+    pub is_public: bool,
+
+    // The number of outstanding references to this name. When this reaches
+    // zero, outside modules can count on the targets being correct. Before
+    // then, all bets are off; future imports could override this name.
+    // Note that this is usually either 0 or 1 - shadowing is forbidden the only
+    // way outstanding_references is > 1 in a legal program is if the name is
+    // used in both namespaces.
+    pub outstanding_references: uint,
+
+    /// The value that this `use` directive names, if there is one.
+    pub value_target: Option<Target>,
+    /// The source node of the `use` directive leading to the value target
+    /// being non-none
+    pub value_id: NodeId,
+
+    /// The type that this `use` directive names, if there is one.
+    pub type_target: Option<Target>,
+    /// The source node of the `use` directive leading to the type target
+    /// being non-none
+    pub type_id: NodeId,
+}
+
+impl ImportResolution {
+    pub fn new(id: NodeId, is_public: bool) -> ImportResolution {
+        ImportResolution {
+            type_id: id,
+            value_id: id,
+            outstanding_references: 0,
+            value_target: None,
+            type_target: None,
+            is_public: is_public,
+        }
+    }
+
+    pub fn target_for_namespace(&self, namespace: Namespace)
+                                -> Option<Target> {
+        match namespace {
+            TypeNS  => self.type_target.clone(),
+            ValueNS => self.value_target.clone(),
+        }
+    }
+
+    pub fn id(&self, namespace: Namespace) -> NodeId {
+        match namespace {
+            TypeNS  => self.type_id,
+            ValueNS => self.value_id,
+        }
+    }
+
+    pub fn shadowable(&self, namespace: Namespace) -> Shadowable {
+        let target = self.target_for_namespace(namespace);
+        if target.is_none() {
+            return Shadowable::Always;
+        }
+
+        target.unwrap().shadowable
+    }
+
+    pub fn set_target_and_id(&mut self,
+                         namespace: Namespace,
+                         target: Option<Target>,
+                         id: NodeId) {
+        match namespace {
+            TypeNS  => {
+                self.type_target = target;
+                self.type_id = id;
+            }
+            ValueNS => {
+                self.value_target = target;
+                self.value_id = id;
+            }
+        }
+    }
+}
+
+
+struct ImportResolver<'a, 'b:'a, 'tcx:'b> {
+    resolver: &'a mut Resolver<'b, 'tcx>
+}
+
+impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
+    // Import resolution
+    //
+    // This is a fixed-point algorithm. We resolve imports until our efforts
+    // are stymied by an unresolved import; then we bail out of the current
+    // module and continue. We terminate successfully once no more imports
+    // remain or unsuccessfully when no forward progress in resolving imports
+    // is made.
+
+    /// Resolves all imports for the crate. This method performs the fixed-
+    /// point iteration.
+    fn resolve_imports(&mut self) {
+        let mut i = 0;
+        let mut prev_unresolved_imports = 0;
+        loop {
+            debug!("(resolving imports) iteration {}, {} imports left",
+                   i, self.resolver.unresolved_imports);
+
+            let module_root = self.resolver.graph_root.get_module();
+            self.resolve_imports_for_module_subtree(module_root.clone());
+
+            if self.resolver.unresolved_imports == 0 {
+                debug!("(resolving imports) success");
+                break;
+            }
+
+            if self.resolver.unresolved_imports == prev_unresolved_imports {
+                self.resolver.report_unresolved_imports(module_root);
+                break;
+            }
+
+            i += 1;
+            prev_unresolved_imports = self.resolver.unresolved_imports;
+        }
+    }
+
+    /// Attempts to resolve imports for the given module and all of its
+    /// submodules.
+    fn resolve_imports_for_module_subtree(&mut self, module_: Rc<Module>) {
+        debug!("(resolving imports for module subtree) resolving {}",
+               module_to_string(&*module_));
+        let orig_module = replace(&mut self.resolver.current_module, module_.clone());
+        self.resolve_imports_for_module(module_.clone());
+        self.resolver.current_module = orig_module;
+
+        build_reduced_graph::populate_module_if_necessary(self.resolver, &module_);
+        for (_, child_node) in &*module_.children.borrow() {
+            match child_node.get_module_if_available() {
+                None => {
+                    // Nothing to do.
+                }
+                Some(child_module) => {
+                    self.resolve_imports_for_module_subtree(child_module);
+                }
+            }
+        }
+
+        for (_, child_module) in &*module_.anonymous_children.borrow() {
+            self.resolve_imports_for_module_subtree(child_module.clone());
+        }
+    }
+
+    /// Attempts to resolve imports for the given module only.
+    fn resolve_imports_for_module(&mut self, module: Rc<Module>) {
+        if module.all_imports_resolved() {
+            debug!("(resolving imports for module) all imports resolved for \
+                   {}",
+                   module_to_string(&*module));
+            return;
+        }
+
+        let imports = module.imports.borrow();
+        let import_count = imports.len();
+        while module.resolved_import_count.get() < import_count {
+            let import_index = module.resolved_import_count.get();
+            let import_directive = &(*imports)[import_index];
+            match self.resolve_import_for_module(module.clone(),
+                                                 import_directive) {
+                ResolveResult::Failed(err) => {
+                    let (span, help) = match err {
+                        Some((span, msg)) => (span, format!(". {}", msg)),
+                        None => (import_directive.span, String::new())
+                    };
+                    let msg = format!("unresolved import `{}`{}",
+                                      import_path_to_string(
+                                          &import_directive.module_path,
+                                          import_directive.subclass),
+                                      help);
+                    self.resolver.resolve_error(span, &msg[..]);
+                }
+                ResolveResult::Indeterminate => break, // Bail out. We'll come around next time.
+                ResolveResult::Success(()) => () // Good. Continue.
+            }
+
+            module.resolved_import_count
+                  .set(module.resolved_import_count.get() + 1);
+        }
+    }
+
+    /// Attempts to resolve the given import. The return value indicates
+    /// failure if we're certain the name does not exist, indeterminate if we
+    /// don't know whether the name exists at the moment due to other
+    /// currently-unresolved imports, or success if we know the name exists.
+    /// If successful, the resolved bindings are written into the module.
+    fn resolve_import_for_module(&mut self,
+                                 module_: Rc<Module>,
+                                 import_directive: &ImportDirective)
+                                 -> ResolveResult<()> {
+        let mut resolution_result = ResolveResult::Failed(None);
+        let module_path = &import_directive.module_path;
+
+        debug!("(resolving import for module) resolving import `{}::...` in `{}`",
+               names_to_string(&module_path[..]),
+               module_to_string(&*module_));
+
+        // First, resolve the module path for the directive, if necessary.
+        let container = if module_path.len() == 0 {
+            // Use the crate root.
+            Some((self.resolver.graph_root.get_module(), LastMod(AllPublic)))
+        } else {
+            match self.resolver.resolve_module_path(module_.clone(),
+                                                    &module_path[..],
+                                                    UseLexicalScopeFlag::DontUseLexicalScope,
+                                                    import_directive.span,
+                                                    NameSearchType::ImportSearch) {
+                ResolveResult::Failed(err) => {
+                    resolution_result = ResolveResult::Failed(err);
+                    None
+                },
+                ResolveResult::Indeterminate => {
+                    resolution_result = ResolveResult::Indeterminate;
+                    None
+                }
+                ResolveResult::Success(container) => Some(container),
+            }
+        };
+
+        match container {
+            None => {}
+            Some((containing_module, lp)) => {
+                // We found the module that the target is contained
+                // within. Attempt to resolve the import within it.
+
+                match import_directive.subclass {
+                    SingleImport(target, source) => {
+                        resolution_result =
+                            self.resolve_single_import(&module_,
+                                                       containing_module,
+                                                       target,
+                                                       source,
+                                                       import_directive,
+                                                       lp);
+                    }
+                    GlobImport => {
+                        resolution_result =
+                            self.resolve_glob_import(&module_,
+                                                     containing_module,
+                                                     import_directive,
+                                                     lp);
+                    }
+                }
+            }
+        }
+
+        // Decrement the count of unresolved imports.
+        match resolution_result {
+            ResolveResult::Success(()) => {
+                assert!(self.resolver.unresolved_imports >= 1);
+                self.resolver.unresolved_imports -= 1;
+            }
+            _ => {
+                // Nothing to do here; just return the error.
+            }
+        }
+
+        // Decrement the count of unresolved globs if necessary. But only if
+        // the resolution result is indeterminate -- otherwise we'll stop
+        // processing imports here. (See the loop in
+        // resolve_imports_for_module).
+
+        if !resolution_result.indeterminate() {
+            match import_directive.subclass {
+                GlobImport => {
+                    assert!(module_.glob_count.get() >= 1);
+                    module_.glob_count.set(module_.glob_count.get() - 1);
+                }
+                SingleImport(..) => {
+                    // Ignore.
+                }
+            }
+        }
+
+        return resolution_result;
+    }
+
+    fn resolve_single_import(&mut self,
+                             module_: &Module,
+                             target_module: Rc<Module>,
+                             target: Name,
+                             source: Name,
+                             directive: &ImportDirective,
+                             lp: LastPrivate)
+                             -> ResolveResult<()> {
+        debug!("(resolving single import) resolving `{}` = `{}::{}` from \
+                `{}` id {}, last private {:?}",
+               token::get_name(target),
+               module_to_string(&*target_module),
+               token::get_name(source),
+               module_to_string(module_),
+               directive.id,
+               lp);
+
+        let lp = match lp {
+            LastMod(lp) => lp,
+            LastImport {..} => {
+                self.resolver.session
+                    .span_bug(directive.span,
+                              "not expecting Import here, must be LastMod")
+            }
+        };
+
+        // We need to resolve both namespaces for this to succeed.
+        //
+
+        let mut value_result = UnknownResult;
+        let mut type_result = UnknownResult;
+
+        // Search for direct children of the containing module.
+        build_reduced_graph::populate_module_if_necessary(self.resolver, &target_module);
+
+        match target_module.children.borrow().get(&source) {
+            None => {
+                // Continue.
+            }
+            Some(ref child_name_bindings) => {
+                // pub_err makes sure we don't give the same error twice.
+                let mut pub_err = false;
+                if child_name_bindings.defined_in_namespace(ValueNS) {
+                    debug!("(resolving single import) found value binding");
+                    value_result = BoundResult(target_module.clone(),
+                                               (*child_name_bindings).clone());
+                    if directive.is_public && !child_name_bindings.is_public(ValueNS) {
+                        let msg = format!("`{}` is private", token::get_name(source));
+                        span_err!(self.resolver.session, directive.span, E0364, "{}", &msg);
+                        pub_err = true;
+                    }
+                }
+                if child_name_bindings.defined_in_namespace(TypeNS) {
+                    debug!("(resolving single import) found type binding");
+                    type_result = BoundResult(target_module.clone(),
+                                              (*child_name_bindings).clone());
+                    if !pub_err && directive.is_public && !child_name_bindings.is_public(TypeNS) {
+                        let msg = format!("`{}` is private", token::get_name(source));
+                        span_err!(self.resolver.session, directive.span, E0365, "{}", &msg);
+                    }
+                }
+            }
+        }
+
+        // Unless we managed to find a result in both namespaces (unlikely),
+        // search imports as well.
+        let mut value_used_reexport = false;
+        let mut type_used_reexport = false;
+        match (value_result.clone(), type_result.clone()) {
+            (BoundResult(..), BoundResult(..)) => {} // Continue.
+            _ => {
+                // 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 this import.
+
+                if target_module.glob_count.get() > 0 {
+                    debug!("(resolving single import) unresolved glob; \
+                            bailing out");
+                    return ResolveResult::Indeterminate;
+                }
+
+                // Now search the exported imports within the containing module.
+                match target_module.import_resolutions.borrow().get(&source) {
+                    None => {
+                        debug!("(resolving single import) no import");
+                        // The containing module definitely doesn't have an
+                        // exported import with the name in question. We can
+                        // therefore accurately report that the names are
+                        // unbound.
+
+                        if value_result.is_unknown() {
+                            value_result = UnboundResult;
+                        }
+                        if type_result.is_unknown() {
+                            type_result = UnboundResult;
+                        }
+                    }
+                    Some(import_resolution)
+                            if import_resolution.outstanding_references == 0 => {
+
+                        fn get_binding(this: &mut Resolver,
+                                       import_resolution: &ImportResolution,
+                                       namespace: Namespace,
+                                       source: &Name)
+                                    -> NamespaceResult {
+
+                            // Import resolutions must be declared with "pub"
+                            // in order to be exported.
+                            if !import_resolution.is_public {
+                                return UnboundResult;
+                            }
+
+                            match import_resolution.target_for_namespace(namespace) {
+                                None => {
+                                    return UnboundResult;
+                                }
+                                Some(Target {
+                                    target_module,
+                                    bindings,
+                                    shadowable: _
+                                }) => {
+                                    debug!("(resolving single import) found \
+                                            import in ns {:?}", namespace);
+                                    let id = import_resolution.id(namespace);
+                                    // track used imports and extern crates as well
+                                    this.used_imports.insert((id, namespace));
+                                    this.record_import_use(id, *source);
+                                    match target_module.def_id.get() {
+                                        Some(DefId{krate: kid, ..}) => {
+                                            this.used_crates.insert(kid);
+                                        },
+                                        _ => {}
+                                    }
+                                    return BoundResult(target_module, bindings);
+                                }
+                            }
+                        }
+
+                        // The name is an import which has been fully
+                        // resolved. We can, therefore, just follow it.
+                        if value_result.is_unknown() {
+                            value_result = get_binding(self.resolver,
+                                                       import_resolution,
+                                                       ValueNS,
+                                                       &source);
+                            value_used_reexport = import_resolution.is_public;
+                        }
+                        if type_result.is_unknown() {
+                            type_result = get_binding(self.resolver,
+                                                      import_resolution,
+                                                      TypeNS,
+                                                      &source);
+                            type_used_reexport = import_resolution.is_public;
+                        }
+
+                    }
+                    Some(_) => {
+                        // If target_module is the same module whose import we are resolving
+                        // and there it has an unresolved import with the same name as `source`,
+                        // 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 the
+                        // check_for_conflicts_between_imports_and_items call below handle
+                        // the conflict
+                        match (module_.def_id.get(),  target_module.def_id.get()) {
+                            (Some(id1), Some(id2)) if id1 == id2  => {
+                                if value_result.is_unknown() {
+                                    value_result = UnboundResult;
+                                }
+                                if type_result.is_unknown() {
+                                    type_result = UnboundResult;
+                                }
+                            }
+                            _ =>  {
+                                // The import is unresolved. Bail out.
+                                debug!("(resolving single import) unresolved import; \
+                                        bailing out");
+                                return ResolveResult::Indeterminate;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        let mut value_used_public = false;
+        let mut type_used_public = false;
+
+        // If we didn't find a result in the type namespace, search the
+        // external modules.
+        match type_result {
+            BoundResult(..) => {}
+            _ => {
+                match target_module.external_module_children.borrow_mut().get(&source).cloned() {
+                    None => {} // Continue.
+                    Some(module) => {
+                        debug!("(resolving single import) found external module");
+                        // track the module as used.
+                        match module.def_id.get() {
+                            Some(DefId{krate: kid, ..}) => {
+                                self.resolver.used_crates.insert(kid);
+                            }
+                            _ => {}
+                        }
+                        let name_bindings =
+                            Rc::new(Resolver::create_name_bindings_from_module(module));
+                        type_result = BoundResult(target_module.clone(), name_bindings);
+                        type_used_public = true;
+                    }
+                }
+            }
+        }
+
+        // We've successfully resolved the import. Write the results in.
+        let mut import_resolutions = module_.import_resolutions.borrow_mut();
+        let import_resolution = &mut (*import_resolutions)[target];
+
+        {
+            let mut check_and_write_import = |namespace, result: &_, used_public: &mut bool| {
+                let namespace_name = match namespace {
+                    TypeNS => "type",
+                    ValueNS => "value",
+                };
+
+                match *result {
+                    BoundResult(ref target_module, ref name_bindings) => {
+                        debug!("(resolving single import) found {:?} target: {:?}",
+                               namespace_name,
+                               name_bindings.def_for_namespace(namespace));
+                        self.check_for_conflicting_import(
+                            &import_resolution.target_for_namespace(namespace),
+                            directive.span,
+                            target,
+                            namespace);
+
+                        self.check_that_import_is_importable(
+                            &**name_bindings,
+                            directive.span,
+                            target,
+                            namespace);
+
+                        let target = Some(Target::new(target_module.clone(),
+                                                      name_bindings.clone(),
+                                                      directive.shadowable));
+                        import_resolution.set_target_and_id(namespace, target, directive.id);
+                        import_resolution.is_public = directive.is_public;
+                        *used_public = name_bindings.defined_in_public_namespace(namespace);
+                    }
+                    UnboundResult => { /* Continue. */ }
+                    UnknownResult => {
+                        panic!("{:?} result should be known at this point", namespace_name);
+                    }
+                }
+            };
+            check_and_write_import(ValueNS, &value_result, &mut value_used_public);
+            check_and_write_import(TypeNS, &type_result, &mut type_used_public);
+        }
+
+        self.check_for_conflicts_between_imports_and_items(
+            module_,
+            import_resolution,
+            directive.span,
+            target);
+
+        if value_result.is_unbound() && type_result.is_unbound() {
+            let msg = format!("There is no `{}` in `{}`",
+                              token::get_name(source),
+                              module_to_string(&target_module));
+            return ResolveResult::Failed(Some((directive.span, msg)));
+        }
+        let value_used_public = value_used_reexport || value_used_public;
+        let type_used_public = type_used_reexport || type_used_public;
+
+        assert!(import_resolution.outstanding_references >= 1);
+        import_resolution.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.
+        let value_def_and_priv = import_resolution.value_target.as_ref().map(|target| {
+            let def = target.bindings.def_for_namespace(ValueNS).unwrap();
+            (def, if value_used_public { lp } else { DependsOn(def.def_id()) })
+        });
+        let type_def_and_priv = import_resolution.type_target.as_ref().map(|target| {
+            let def = target.bindings.def_for_namespace(TypeNS).unwrap();
+            (def, if type_used_public { lp } else { DependsOn(def.def_id()) })
+        });
+
+        let import_lp = LastImport {
+            value_priv: value_def_and_priv.map(|(_, p)| p),
+            value_used: Used,
+            type_priv: type_def_and_priv.map(|(_, p)| p),
+            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
+            });
+        }
+
+        debug!("(resolving single import) successfully resolved import");
+        return ResolveResult::Success(());
+    }
+
+    // Resolves a glob import. Note that this function cannot fail; it either
+    // succeeds or bails out (as importing * from an empty module or a module
+    // that exports nothing is valid). target_module is the module we are
+    // actually importing, i.e., `foo` in `use foo::*`.
+    fn resolve_glob_import(&mut self,
+                           module_: &Module,
+                           target_module: Rc<Module>,
+                           import_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).all_imports_resolved() {
+            debug!("(resolving glob import) target module has unresolved \
+                    imports; bailing out");
+            return ResolveResult::Indeterminate;
+        }
+
+        assert_eq!(target_module.glob_count.get(), 0);
+
+        // Add all resolved imports from the containing module.
+        let import_resolutions = target_module.import_resolutions.borrow();
+        for (ident, target_import_resolution) in &*import_resolutions {
+            debug!("(resolving glob import) writing module resolution \
+                    {} into `{}`",
+                   token::get_name(*ident),
+                   module_to_string(module_));
+
+            if !target_import_resolution.is_public {
+                debug!("(resolving glob import) nevermind, just kidding");
+                continue
+            }
+
+            // Here we merge two import resolutions.
+            let mut import_resolutions = module_.import_resolutions.borrow_mut();
+            match import_resolutions.get_mut(ident) {
+                Some(dest_import_resolution) => {
+                    // Merge the two import resolutions at a finer-grained
+                    // level.
+
+                    match target_import_resolution.value_target {
+                        None => {
+                            // Continue.
+                        }
+                        Some(ref value_target) => {
+                            self.check_for_conflicting_import(&dest_import_resolution.value_target,
+                                                              import_directive.span,
+                                                              *ident,
+                                                              ValueNS);
+                            dest_import_resolution.value_target = Some(value_target.clone());
+                        }
+                    }
+                    match target_import_resolution.type_target {
+                        None => {
+                            // Continue.
+                        }
+                        Some(ref type_target) => {
+                            self.check_for_conflicting_import(&dest_import_resolution.type_target,
+                                                              import_directive.span,
+                                                              *ident,
+                                                              TypeNS);
+                            dest_import_resolution.type_target = Some(type_target.clone());
+                        }
+                    }
+                    dest_import_resolution.is_public = is_public;
+                    continue;
+                }
+                None => {}
+            }
+
+            // Simple: just copy the old import resolution.
+            let mut new_import_resolution = ImportResolution::new(id, is_public);
+            new_import_resolution.value_target =
+                target_import_resolution.value_target.clone();
+            new_import_resolution.type_target =
+                target_import_resolution.type_target.clone();
+
+            import_resolutions.insert(*ident, new_import_resolution);
+        }
+
+        // Add all children from the containing module.
+        build_reduced_graph::populate_module_if_necessary(self.resolver, &target_module);
+
+        for (&name, name_bindings) in &*target_module.children.borrow() {
+            self.merge_import_resolution(module_,
+                                         target_module.clone(),
+                                         import_directive,
+                                         name,
+                                         name_bindings.clone());
+
+        }
+
+        // Add external module children from the containing module.
+        for (&name, module) in &*target_module.external_module_children.borrow() {
+            let name_bindings =
+                Rc::new(Resolver::create_name_bindings_from_module(module.clone()));
+            self.merge_import_resolution(module_,
+                                         target_module.clone(),
+                                         import_directive,
+                                         name,
+                                         name_bindings);
+        }
+
+        // Record the destination of this import
+        if let Some(did) = target_module.def_id.get() {
+            self.resolver.def_map.borrow_mut().insert(id, PathResolution {
+                base_def: DefMod(did),
+                last_private: lp,
+                depth: 0
+            });
+        }
+
+        debug!("(resolving glob import) successfully resolved import");
+        return ResolveResult::Success(());
+    }
+
+    fn merge_import_resolution(&mut self,
+                               module_: &Module,
+                               containing_module: Rc<Module>,
+                               import_directive: &ImportDirective,
+                               name: Name,
+                               name_bindings: Rc<NameBindings>) {
+        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).get().unwrap_or_else(
+            |vacant_entry| {
+                // Create a new import resolution from this child.
+                vacant_entry.insert(ImportResolution::new(id, is_public))
+            });
+
+        debug!("(resolving glob import) writing resolution `{}` in `{}` \
+               to `{}`",
+               &token::get_name(name),
+               module_to_string(&*containing_module),
+               module_to_string(module_));
+
+        // Merge the child item into the import resolution.
+        {
+            let mut merge_child_item = |namespace| {
+                if name_bindings.defined_in_namespace_with(namespace, IMPORTABLE | PUBLIC) {
+                    let namespace_name = match namespace {
+                        TypeNS => "type",
+                        ValueNS => "value",
+                    };
+                    debug!("(resolving glob import) ... for {} target", namespace_name);
+                    if dest_import_resolution.shadowable(namespace) == Shadowable::Never {
+                        let msg = format!("a {} named `{}` has already been imported \
+                                           in this module",
+                                          namespace_name,
+                                          &token::get_name(name));
+                        span_err!(self.resolver.session, import_directive.span, E0251, "{}", msg);
+                    } else {
+                        let target = Target::new(containing_module.clone(),
+                                                 name_bindings.clone(),
+                                                 import_directive.shadowable);
+                        dest_import_resolution.set_target_and_id(namespace,
+                                                                 Some(target),
+                                                                 id);
+                    }
+                }
+            };
+            merge_child_item(ValueNS);
+            merge_child_item(TypeNS);
+        }
+
+        dest_import_resolution.is_public = is_public;
+
+        self.check_for_conflicts_between_imports_and_items(
+            module_,
+            dest_import_resolution,
+            import_directive.span,
+            name);
+    }
+
+    /// Checks that imported names and items don't have the same name.
+    fn check_for_conflicting_import(&mut self,
+                                    target: &Option<Target>,
+                                    import_span: Span,
+                                    name: Name,
+                                    namespace: Namespace) {
+        debug!("check_for_conflicting_import: {}; target exists: {}",
+               &token::get_name(name),
+               target.is_some());
+
+        match *target {
+            Some(ref target) if target.shadowable != Shadowable::Always => {
+                let msg = format!("a {} named `{}` has already been imported \
+                                   in this module",
+                                  match namespace {
+                                    TypeNS => "type",
+                                    ValueNS => "value",
+                                  },
+                                  &token::get_name(name));
+                span_err!(self.resolver.session, import_span, E0252, "{}", &msg[..]);
+            }
+            Some(_) | None => {}
+        }
+    }
+
+    /// Checks that an import is actually importable
+    fn check_that_import_is_importable(&mut self,
+                                       name_bindings: &NameBindings,
+                                       import_span: Span,
+                                       name: Name,
+                                       namespace: Namespace) {
+        if !name_bindings.defined_in_namespace_with(namespace, IMPORTABLE) {
+            let msg = format!("`{}` is not directly importable",
+                              token::get_name(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,
+                                                     import_resolution:
+                                                     &ImportResolution,
+                                                     import_span: Span,
+                                                     name: Name) {
+        // First, check for conflicts between imports and `extern crate`s.
+        if module.external_module_children
+                 .borrow()
+                 .contains_key(&name) {
+            match import_resolution.type_target {
+                Some(ref target) if target.shadowable != Shadowable::Always => {
+                    let msg = format!("import `{0}` conflicts with imported \
+                                       crate in this module \
+                                       (maybe you meant `use {0}::*`?)",
+                                      &token::get_name(name));
+                    span_err!(self.resolver.session, import_span, E0254, "{}", &msg[..]);
+                }
+                Some(_) | None => {}
+            }
+        }
+
+        // Check for item conflicts.
+        let children = module.children.borrow();
+        let name_bindings = match children.get(&name) {
+            None => {
+                // There can't be any conflicts.
+                return
+            }
+            Some(ref name_bindings) => (*name_bindings).clone(),
+        };
+
+        match import_resolution.value_target {
+            Some(ref target) if target.shadowable != Shadowable::Always => {
+                if let Some(ref value) = *name_bindings.value_def.borrow() {
+                    span_err!(self.resolver.session, import_span, E0255,
+                              "import `{}` conflicts with value in this module",
+                              &token::get_name(name));
+                    if let Some(span) = value.value_span {
+                        self.resolver.session.span_note(span, "conflicting value here");
+                    }
+                }
+            }
+            Some(_) | None => {}
+        }
+
+        match import_resolution.type_target {
+            Some(ref target) if target.shadowable != Shadowable::Always => {
+                if let Some(ref ty) = *name_bindings.type_def.borrow() {
+                    let (what, note) = if ty.module_def.is_some() {
+                        ("existing submodule", "note conflicting module here")
+                    } else {
+                        ("type in this module", "note conflicting type here")
+                    };
+                    span_err!(self.resolver.session, import_span, E0256,
+                              "import `{}` conflicts with {}",
+                              &token::get_name(name), what);
+                    if let Some(span) = ty.type_span {
+                        self.resolver.session.span_note(span, note);
+                    }
+                }
+            }
+            Some(_) | None => {}
+        }
+    }
+}
+
+fn import_path_to_string(names: &[Name],
+                         subclass: ImportDirectiveSubclass)
+                         -> String {
+    if names.is_empty() {
+        import_directive_subclass_to_string(subclass)
+    } else {
+        (format!("{}::{}",
+                 names_to_string(names),
+                 import_directive_subclass_to_string(subclass))).to_string()
+    }
+}
+
+fn import_directive_subclass_to_string(subclass: ImportDirectiveSubclass) -> String {
+    match subclass {
+        SingleImport(_, source) => {
+            token::get_name(source).to_string()
+        }
+        GlobImport => "*".to_string()
+    }
+}
+
+pub fn resolve_imports(resolver: &mut Resolver) {
+    let mut import_resolver = ImportResolver {
+        resolver: resolver,
+    };
+    import_resolver.resolve_imports();
+}