about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-12-27 00:48:41 +0000
committerbors <bors@rust-lang.org>2014-12-27 00:48:41 +0000
commit3c60bc02ce6de2823d0b837f90d5db0077fce6f7 (patch)
tree465805adb25fba470b8da95ff820a363f32a8dee
parentc06edbad34f2f8f2fa5138e855a442db1c6324d1 (diff)
parent4b92a5a229ebe7635851fc7bad94108f9de8dcc6 (diff)
downloadrust-3c60bc02ce6de2823d0b837f90d5db0077fce6f7.tar.gz
rust-3c60bc02ce6de2823d0b837f90d5db0077fce6f7.zip
auto merge of #19254 : nick29581/rust/dxr-glob, r=pcwalton
There is also some work here to make resolve a bit more stable - it no longer overwrites a specific import with a glob import.

r?
-rw-r--r--src/libcollections/str.rs2
-rw-r--r--src/libgraphviz/maybe_owned_vec.rs1
-rw-r--r--src/librustc/metadata/csearch.rs7
-rw-r--r--src/librustc/metadata/decoder.rs8
-rw-r--r--src/librustc/middle/ty.rs7
-rw-r--r--src/librustc_borrowck/borrowck/check_loans.rs2
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs1
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/mod.rs1
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/restrictions.rs2
-rw-r--r--src/librustc_driver/driver.rs21
-rw-r--r--src/librustc_driver/test.rs2
-rw-r--r--src/librustc_resolve/check_unused.rs16
-rw-r--r--src/librustc_resolve/lib.rs215
-rw-r--r--src/librustc_resolve/record_exports.rs14
-rw-r--r--src/librustc_trans/save/mod.rs24
-rw-r--r--src/librustc_trans/save/recorder.rs14
-rw-r--r--src/librustc_trans/save/span_utils.rs13
-rw-r--r--src/librustc_trans/trans/mod.rs1
-rw-r--r--src/libstd/ascii.rs2
-rw-r--r--src/libstd/c_str.rs3
-rw-r--r--src/libstd/comm/mod.rs9
-rw-r--r--src/libstd/io/mem.rs2
-rw-r--r--src/libstd/io/net/pipe.rs2
-rw-r--r--src/libstd/io/net/udp.rs4
-rw-r--r--src/libstd/io/process.rs2
-rw-r--r--src/libstd/path/posix.rs4
-rw-r--r--src/libstd/path/windows.rs4
27 files changed, 286 insertions, 97 deletions
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs
index 5feae5e558e..bccd2a1198a 100644
--- a/src/libcollections/str.rs
+++ b/src/libcollections/str.rs
@@ -3330,10 +3330,10 @@ mod tests {
 
 #[cfg(test)]
 mod bench {
+    use super::*;
     use prelude::*;
     use test::Bencher;
     use test::black_box;
-    use super::*;
 
     #[bench]
     fn char_iterator(b: &mut Bencher) {
diff --git a/src/libgraphviz/maybe_owned_vec.rs b/src/libgraphviz/maybe_owned_vec.rs
index 88483b6c935..ddda2b38c22 100644
--- a/src/libgraphviz/maybe_owned_vec.rs
+++ b/src/libgraphviz/maybe_owned_vec.rs
@@ -14,7 +14,6 @@ pub use self::MaybeOwnedVector::*;
 
 use std::default::Default;
 use std::fmt;
-use std::iter::FromIterator;
 use std::path::BytesContainer;
 use std::slice;
 
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index 13342bf82cf..51cebbfb52c 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -146,6 +146,13 @@ pub fn get_impl_or_trait_item<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId)
                                     tcx)
 }
 
+pub fn get_trait_name(cstore: &cstore::CStore, def: ast::DefId) -> ast::Name {
+    let cdata = cstore.get_crate_data(def.krate);
+    decoder::get_trait_name(cstore.intr.clone(),
+                            &*cdata,
+                            def.node)
+}
+
 pub fn get_trait_item_name_and_kind(cstore: &cstore::CStore, def: ast::DefId)
                                     -> (ast::Name, def::TraitItemKind) {
     let cdata = cstore.get_crate_data(def.krate);
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index f05607a999b..ee928828827 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -781,6 +781,14 @@ pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
     impl_items
 }
 
+pub fn get_trait_name(intr: Rc<IdentInterner>,
+                      cdata: Cmd,
+                      id: ast::NodeId)
+                      -> ast::Name {
+    let doc = lookup_item(id, cdata.data());
+    item_name(&*intr, doc)
+}
+
 pub fn get_trait_item_name_and_kind(intr: Rc<IdentInterner>,
                                     cdata: Cmd,
                                     id: ast::NodeId)
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 9c1259f4120..c0d5d6b11cf 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -77,7 +77,7 @@ use std::mem;
 use std::ops;
 use std::rc::Rc;
 use collections::enum_set::{EnumSet, CLike};
-use std::collections::hash_map::HashMap;
+use std::collections::{HashMap, HashSet};
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 use syntax::abi;
 use syntax::ast::{CrateNum, DefId, DUMMY_NODE_ID, Ident, ItemTrait, LOCAL_CRATE};
@@ -105,6 +105,7 @@ pub struct CrateAnalysis<'tcx> {
     pub ty_cx: ty::ctxt<'tcx>,
     pub reachable: NodeSet,
     pub name: String,
+    pub glob_map: Option<GlobMap>,
 }
 
 #[deriving(Copy, PartialEq, Eq, Hash)]
@@ -6285,6 +6286,10 @@ pub type CaptureModeMap = NodeMap<ast::CaptureClause>;
 // Trait method resolution
 pub type TraitMap = NodeMap<Vec<DefId>>;
 
+// Map from the NodeId of a glob import to a list of items which are actually
+// imported.
+pub type GlobMap = HashMap<NodeId, HashSet<Name>>;
+
 pub fn with_freevars<T, F>(tcx: &ty::ctxt, fid: ast::NodeId, f: F) -> T where
     F: FnOnce(&[Freevar]) -> T,
 {
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index 568bb023b68..046b9547cbb 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -19,8 +19,6 @@
 use self::UseError::*;
 
 use borrowck::*;
-use borrowck::LoanPathElem::*;
-use borrowck::LoanPathKind::*;
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::region;
diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
index 01cbab6dbf4..85cc691fb9d 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
@@ -11,7 +11,6 @@
 //! Computes moves.
 
 use borrowck::*;
-use borrowck::LoanPathKind::*;
 use borrowck::gather_loans::move_error::MoveSpanAndPath;
 use borrowck::gather_loans::move_error::{MoveError, MoveErrorCollector};
 use borrowck::move_data::*;
diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
index d7f50ccc6ba..c0e892cdd27 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
@@ -17,7 +17,6 @@
 // sure that all of these loans are honored.
 
 use borrowck::*;
-use borrowck::LoanPathKind::*;
 use borrowck::move_data::MoveData;
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization as mc;
diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
index c783489dab7..fc15c0eb4ec 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
@@ -13,8 +13,6 @@
 pub use self::RestrictionResult::*;
 
 use borrowck::*;
-use borrowck::LoanPathElem::*;
-use borrowck::LoanPathKind::*;
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::ty;
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 20bb9c2f4fd..4ab5c19430b 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -342,6 +342,11 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
     let lang_items = time(time_passes, "language item collection", (), |_|
                           middle::lang_items::collect_language_items(krate, &sess));
 
+    let make_glob_map = if save_analysis(&sess) {
+        resolve::MakeGlobMap::Yes
+    } else {
+        resolve::MakeGlobMap::No
+    };
     let resolve::CrateMap {
         def_map,
         freevars,
@@ -349,10 +354,15 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
         export_map,
         trait_map,
         external_exports,
-        last_private_map
+        last_private_map,
+        glob_map,
     } =
         time(time_passes, "resolution", (),
-             |_| resolve::resolve_crate(&sess, &lang_items, krate));
+             |_| resolve::resolve_crate(&sess,
+                                        &ast_map,
+                                        &lang_items,
+                                        krate,
+                                        make_glob_map));
 
     // Discard MTWT tables that aren't required past resolution.
     syntax::ext::mtwt::clear_tables();
@@ -454,14 +464,19 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
         public_items: public_items,
         reachable: reachable_map,
         name: name,
+        glob_map: glob_map,
     }
 }
 
+fn save_analysis(sess: &Session) -> bool {
+    (sess.opts.debugging_opts & config::SAVE_ANALYSIS) != 0
+}
+
 pub fn phase_save_analysis(sess: &Session,
                            krate: &ast::Crate,
                            analysis: &ty::CrateAnalysis,
                            odir: &Option<Path>) {
-    if (sess.opts.debugging_opts & config::SAVE_ANALYSIS) == 0 {
+    if !save_analysis(sess) {
         return;
     }
     time(sess.time_passes(), "save analysis", krate, |krate|
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 526bbca8d70..1ef1486dd54 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -123,7 +123,7 @@ fn test_env<F>(source_string: &str,
     // run just enough stuff to build a tcx:
     let lang_items = lang_items::collect_language_items(krate, &sess);
     let resolve::CrateMap { def_map, freevars, capture_mode_map, .. } =
-        resolve::resolve_crate(&sess, &lang_items, krate);
+        resolve::resolve_crate(&sess, &ast_map, &lang_items, krate, resolve::MakeGlobMap::No);
     let named_region_map = resolve_lifetime::krate(&sess, krate, &def_map);
     let region_map = region::resolve_crate(&sess, krate);
     let stability_index = stability::Index::build(krate);
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index 39cdf6fc8f3..78527315199 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -28,24 +28,24 @@ use syntax::ast::{ViewPathGlob, ViewPathList, ViewPathSimple};
 use syntax::codemap::{Span, DUMMY_SP};
 use syntax::visit::{mod, Visitor};
 
-struct UnusedImportCheckVisitor<'a, 'b:'a> {
-    resolver: &'a mut Resolver<'b>
+struct UnusedImportCheckVisitor<'a, 'b:'a, 'tcx:'b> {
+    resolver: &'a mut Resolver<'b, 'tcx>
 }
 
 // Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver.
-impl<'a, 'b> Deref<Resolver<'b>> for UnusedImportCheckVisitor<'a, 'b> {
-    fn deref<'c>(&'c self) -> &'c Resolver<'b> {
+impl<'a, 'b, 'tcx:'b> Deref<Resolver<'b, 'tcx>> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
+    fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> {
         &*self.resolver
     }
 }
 
-impl<'a, 'b> DerefMut<Resolver<'b>> for UnusedImportCheckVisitor<'a, 'b> {
-    fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> {
+impl<'a, 'b, 'tcx:'b> DerefMut<Resolver<'b, 'tcx>> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
+    fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> {
         &mut *self.resolver
     }
 }
 
-impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> {
+impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
     // We have information about whether `use` (import) directives are actually used now.
     // If an import is not used at all, we signal a lint error. If an import is only used
     // for a single namespace, we remove the other namespace from the recorded privacy
@@ -104,7 +104,7 @@ impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> {
     }
 }
 
-impl<'a, 'b, 'v> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b> {
+impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
     fn visit_view_item(&mut self, vi: &ViewItem) {
         // Ignore is_public import statements because there's no way to be sure
         // whether they're used or not. Also ignore imports with a dummy span
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index bf9e9294307..720883a8e9a 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -55,7 +55,7 @@ use rustc::middle::lang_items::LanguageItems;
 use rustc::middle::pat_util::pat_bindings;
 use rustc::middle::privacy::*;
 use rustc::middle::subst::{ParamSpace, FnSpace, TypeSpace};
-use rustc::middle::ty::{CaptureModeMap, Freevar, FreevarMap, TraitMap};
+use rustc::middle::ty::{CaptureModeMap, Freevar, FreevarMap, TraitMap, GlobMap};
 use rustc::util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap};
 use rustc::util::lev_distance::lev_distance;
 
@@ -66,7 +66,7 @@ use syntax::ast::{ExprPath, ExprStruct, FnDecl};
 use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic, Generics};
 use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemFn};
 use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
-use syntax::ast::{ItemStruct, ItemTrait, ItemTy, Local};
+use syntax::ast::{ItemStruct, ItemTrait, ItemTy, Local, LOCAL_CRATE};
 use syntax::ast::{MethodImplItem, Mod, Name, NamedField, NodeId};
 use syntax::ast::{Pat, PatEnum, PatIdent, PatLit};
 use syntax::ast::{PatRange, PatStruct, Path, PathListIdent, PathListMod};
@@ -82,6 +82,7 @@ use syntax::ast::{Variant, ViewItem, ViewItemExternCrate};
 use syntax::ast::{ViewItemUse, ViewPathGlob, ViewPathList, ViewPathSimple};
 use syntax::ast::{Visibility};
 use syntax::ast;
+use syntax::ast_map;
 use syntax::ast_util::{mod, PostExpansionMethod, local_def, walk_pat};
 use syntax::attr::AttrMetaMethods;
 use syntax::ext::mtwt;
@@ -168,7 +169,7 @@ enum NameDefinition {
     ImportNameDefinition(Def, LastPrivate) //< The name identifies an import.
 }
 
-impl<'a, 'v> Visitor<'v> for Resolver<'a> {
+impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
     fn visit_item(&mut self, item: &Item) {
         self.resolve_item(item);
     }
@@ -340,6 +341,16 @@ impl Rib {
     }
 }
 
+/// Whether an import can be shadowed by another import.
+#[deriving(Show,PartialEq,Clone,Copy)]
+enum Shadowable {
+    Always,
+    /// Means that the recorded import obeys the glob shadowing rules, i.e., can
+    /// only be shadowed by another glob import.
+    Glob,
+    Never
+}
+
 /// One import directive.
 struct ImportDirective {
     module_path: Vec<Name>,
@@ -347,7 +358,7 @@ struct ImportDirective {
     span: Span,
     id: NodeId,
     is_public: bool, // see note in ImportResolution about how to use this
-    shadowable: bool,
+    shadowable: Shadowable,
 }
 
 impl ImportDirective {
@@ -356,7 +367,7 @@ impl ImportDirective {
            span: Span,
            id: NodeId,
            is_public: bool,
-           shadowable: bool)
+           shadowable: Shadowable)
            -> ImportDirective {
         ImportDirective {
             module_path: module_path,
@@ -374,13 +385,13 @@ impl ImportDirective {
 struct Target {
     target_module: Rc<Module>,
     bindings: Rc<NameBindings>,
-    shadowable: bool,
+    shadowable: Shadowable,
 }
 
 impl Target {
     fn new(target_module: Rc<Module>,
            bindings: Rc<NameBindings>,
-           shadowable: bool)
+           shadowable: Shadowable)
            -> Target {
         Target {
             target_module: target_module,
@@ -442,6 +453,15 @@ impl ImportResolution {
             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
+    }
 }
 
 /// The link from a module up to its nearest parent node.
@@ -842,9 +862,11 @@ fn namespace_error_to_string(ns: NamespaceError) -> &'static str {
 }
 
 /// The main resolver class.
-struct Resolver<'a> {
+struct Resolver<'a, 'tcx:'a> {
     session: &'a Session,
 
+    ast_map: &'a ast_map::Map<'tcx>,
+
     graph_root: NameBindings,
 
     trait_item_map: FnvHashMap<(Name, DefId), TraitItemKind>,
@@ -895,16 +917,21 @@ struct Resolver<'a> {
     // so as to avoid printing duplicate errors
     emit_errors: bool,
 
+    make_glob_map: bool,
+    // Maps imports to the names of items actually imported (this actually maps
+    // all imports, but only glob imports are actually interesting).
+    glob_map: GlobMap,
+
     used_imports: HashSet<(NodeId, Namespace)>,
     used_crates: HashSet<CrateNum>,
 }
 
-struct BuildReducedGraphVisitor<'a, 'b:'a> {
-    resolver: &'a mut Resolver<'b>,
+struct BuildReducedGraphVisitor<'a, 'b:'a, 'tcx:'b> {
+    resolver: &'a mut Resolver<'b, 'tcx>,
     parent: ReducedGraphParent
 }
 
-impl<'a, 'b, 'v> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b> {
+impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
 
     fn visit_item(&mut self, item: &Item) {
         let p = self.resolver.build_reduced_graph_for_item(item, self.parent.clone());
@@ -946,8 +973,11 @@ enum FallbackChecks {
 }
 
 
-impl<'a> Resolver<'a> {
-    fn new(session: &'a Session, crate_span: Span) -> Resolver<'a> {
+impl<'a, 'tcx> Resolver<'a, 'tcx> {
+    fn new(session: &'a Session,
+           ast_map: &'a ast_map::Map<'tcx>,
+           crate_span: Span,
+           make_glob_map: MakeGlobMap) -> Resolver<'a, 'tcx> {
         let graph_root = NameBindings::new();
 
         graph_root.define_module(NoParentLink,
@@ -962,6 +992,8 @@ impl<'a> Resolver<'a> {
         Resolver {
             session: session,
 
+            ast_map: ast_map,
+
             // The outermost module has def ID 0; this is not reflected in the
             // AST.
 
@@ -997,6 +1029,8 @@ impl<'a> Resolver<'a> {
             last_private: NodeMap::new(),
 
             emit_errors: true,
+            make_glob_map: make_glob_map == MakeGlobMap::Yes,
+            glob_map: HashMap::new(),
         }
     }
 
@@ -1610,6 +1644,11 @@ impl<'a> Resolver<'a> {
                                  attr.name() == token::get_name(
                                     special_idents::prelude_import.name)
                              });
+                let shadowable = if shadowable {
+                    Shadowable::Always
+                } else {
+                    Shadowable::Never
+                };
 
                 match view_path.node {
                     ViewPathSimple(binding, ref full_path, id) => {
@@ -1680,7 +1719,11 @@ impl<'a> Resolver<'a> {
                                                     view_path.span,
                                                     id,
                                                     is_public,
-                                                    shadowable);
+                                                    if shadowable == Shadowable::Never {
+                                                        Shadowable::Glob
+                                                    } else {
+                                                        shadowable
+                                                    });
                     }
                 }
             }
@@ -2131,7 +2174,7 @@ impl<'a> Resolver<'a> {
                               span: Span,
                               id: NodeId,
                               is_public: bool,
-                              shadowable: bool) {
+                              shadowable: Shadowable) {
         module_.imports.borrow_mut().push(ImportDirective::new(module_path,
                                                                subclass,
                                                                span,
@@ -2326,6 +2369,29 @@ impl<'a> Resolver<'a> {
         }
     }
 
+    #[inline]
+    fn record_import_use(&mut self, import_id: NodeId, name: Name) {
+        if !self.make_glob_map {
+            return;
+        }
+        if self.glob_map.contains_key(&import_id) {
+            self.glob_map[import_id].insert(name);
+            return;
+        }
+
+        let mut new_set = HashSet::new();
+        new_set.insert(name);
+        self.glob_map.insert(import_id, new_set);
+    }
+
+    fn get_trait_name(&self, did: DefId) -> Name {
+        if did.krate == LOCAL_CRATE {
+            self.ast_map.expect_item(did.node).ident.name
+        } else {
+            csearch::get_trait_name(&self.session.cstore, did)
+        }
+    }
+
     /// 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
@@ -2338,8 +2404,7 @@ impl<'a> Resolver<'a> {
         let mut resolution_result = Failed(None);
         let module_path = &import_directive.module_path;
 
-        debug!("(resolving import for module) resolving import `{}::...` in \
-                `{}`",
+        debug!("(resolving import for module) resolving import `{}::...` in `{}`",
                self.names_to_string(module_path[]),
                self.module_to_string(&*module_));
 
@@ -2526,7 +2591,8 @@ impl<'a> Resolver<'a> {
 
                         fn get_binding(this: &mut Resolver,
                                        import_resolution: &ImportResolution,
-                                       namespace: Namespace)
+                                       namespace: Namespace,
+                                       source: &Name)
                                     -> NamespaceResult {
 
                             // Import resolutions must be declared with "pub"
@@ -2550,6 +2616,7 @@ impl<'a> Resolver<'a> {
                                     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);
@@ -2564,13 +2631,17 @@ impl<'a> Resolver<'a> {
                         // 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);
+                            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);
+                            type_result = get_binding(self,
+                                                      import_resolution,
+                                                      TypeNS,
+                                                      &source);
                             type_used_reexport = import_resolution.is_public;
                         }
 
@@ -2752,7 +2823,7 @@ impl<'a> Resolver<'a> {
         return Success(());
     }
 
-    // Resolves a glob import. Note that this function cannot panic; it either
+    // 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).
     fn resolve_glob_import(&mut self,
@@ -2883,7 +2954,9 @@ impl<'a> Resolver<'a> {
 
         let mut import_resolutions = module_.import_resolutions.borrow_mut();
         let dest_import_resolution = match import_resolutions.entry(name) {
-            Occupied(entry) => entry.into_mut(),
+            Occupied(entry) => {
+                entry.into_mut()
+            }
             Vacant(entry) => {
                 // Create a new import resolution from this child.
                 entry.set(ImportResolution::new(id, is_public))
@@ -2899,19 +2972,33 @@ impl<'a> Resolver<'a> {
         // Merge the child item into the import resolution.
         if name_bindings.defined_in_namespace_with(ValueNS, IMPORTABLE | PUBLIC) {
             debug!("(resolving glob import) ... for value target");
-            dest_import_resolution.value_target =
-                Some(Target::new(containing_module.clone(),
-                                 name_bindings.clone(),
-                                 import_directive.shadowable));
-            dest_import_resolution.value_id = id;
+            if dest_import_resolution.shadowable(ValueNS) == Shadowable::Never {
+                let msg = format!("a value named `{}` has already been imported \
+                                   in this module",
+                                  token::get_name(name).get());
+                self.session.span_err(import_directive.span, msg.as_slice());
+            } else {
+                dest_import_resolution.value_target =
+                    Some(Target::new(containing_module.clone(),
+                                     name_bindings.clone(),
+                                     import_directive.shadowable));
+                dest_import_resolution.value_id = id;
+            }
         }
         if name_bindings.defined_in_namespace_with(TypeNS, IMPORTABLE | PUBLIC) {
             debug!("(resolving glob import) ... for type target");
-            dest_import_resolution.type_target =
-                Some(Target::new(containing_module,
-                                 name_bindings.clone(),
-                                 import_directive.shadowable));
-            dest_import_resolution.type_id = id;
+            if dest_import_resolution.shadowable(TypeNS) == Shadowable::Never {
+                let msg = format!("a type named `{}` has already been imported \
+                                   in this module",
+                                  token::get_name(name).get());
+                self.session.span_err(import_directive.span, msg.as_slice());
+            } else {
+                dest_import_resolution.type_target =
+                    Some(Target::new(containing_module,
+                                     name_bindings.clone(),
+                                     import_directive.shadowable));
+                dest_import_resolution.type_id = id;
+            }
         }
         dest_import_resolution.is_public = is_public;
 
@@ -2933,7 +3020,7 @@ impl<'a> Resolver<'a> {
         }
 
         match *target {
-            Some(ref target) if !target.shadowable => {
+            Some(ref target) if target.shadowable != Shadowable::Always => {
                 let msg = format!("a {} named `{}` has already been imported \
                                    in this module",
                                   match namespace {
@@ -2976,7 +3063,7 @@ impl<'a> Resolver<'a> {
                  .borrow()
                  .contains_key(&name) {
             match import_resolution.type_target {
-                Some(ref target) if !target.shadowable => {
+                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}::*`?)",
@@ -2998,7 +3085,7 @@ impl<'a> Resolver<'a> {
         };
 
         match import_resolution.value_target {
-            Some(ref target) if !target.shadowable => {
+            Some(ref target) if target.shadowable != Shadowable::Always => {
                 if let Some(ref value) = *name_bindings.value_def.borrow() {
                     let msg = format!("import `{}` conflicts with value \
                                        in this module",
@@ -3014,7 +3101,7 @@ impl<'a> Resolver<'a> {
         }
 
         match import_resolution.type_target {
-            Some(ref target) if !target.shadowable => {
+            Some(ref target) if target.shadowable != Shadowable::Always => {
                 if let Some(ref ty) = *name_bindings.type_def.borrow() {
                     match ty.module_def {
                         None => {
@@ -3347,7 +3434,7 @@ impl<'a> Resolver<'a> {
                 debug!("top name bindings succeeded");
                 return Success((Target::new(module_.clone(),
                                             name_bindings.clone(),
-                                            false),
+                                            Shadowable::Never),
                                false));
             }
             Some(_) | None => { /* Not found; continue. */ }
@@ -3369,9 +3456,11 @@ impl<'a> Resolver<'a> {
                     debug!("(resolving item in lexical scope) using \
                             import resolution");
                     // track used imports and extern crates as well
-                    self.used_imports.insert((import_resolution.id(namespace), namespace));
+                    let id = import_resolution.id(namespace);
+                    self.used_imports.insert((id, namespace));
+                    self.record_import_use(id, name);
                     if let Some(DefId{krate: kid, ..}) = target.target_module.def_id.get() {
-                        self.used_crates.insert(kid);
+                         self.used_crates.insert(kid);
                     }
                     return Success((target, false));
                 }
@@ -3384,7 +3473,9 @@ impl<'a> Resolver<'a> {
                 let name_bindings =
                     Rc::new(Resolver::create_name_bindings_from_module(module));
                 debug!("lower name bindings succeeded");
-                return Success((Target::new(module_, name_bindings, false),
+                return Success((Target::new(module_,
+                                            name_bindings,
+                                            Shadowable::Never),
                                 false));
             }
         }
@@ -3608,7 +3699,7 @@ impl<'a> Resolver<'a> {
                 debug!("(resolving name in module) found node as child");
                 return Success((Target::new(module_.clone(),
                                             name_bindings.clone(),
-                                            false),
+                                            Shadowable::Never),
                                false));
             }
             Some(_) | None => {
@@ -3645,7 +3736,9 @@ impl<'a> Resolver<'a> {
                         debug!("(resolving name in module) resolved to \
                                 import");
                         // track used imports and extern crates as well
-                        self.used_imports.insert((import_resolution.id(namespace), namespace));
+                        let id = import_resolution.id(namespace);
+                        self.used_imports.insert((id, namespace));
+                        self.record_import_use(id, name);
                         if let Some(DefId{krate: kid, ..}) = target.target_module.def_id.get() {
                             self.used_crates.insert(kid);
                         }
@@ -3661,7 +3754,9 @@ impl<'a> Resolver<'a> {
             if let Some(module) = module_.external_module_children.borrow().get(&name).cloned() {
                 let name_bindings =
                     Rc::new(Resolver::create_name_bindings_from_module(module));
-                return Success((Target::new(module_, name_bindings, false),
+                return Success((Target::new(module_,
+                                            name_bindings,
+                                            Shadowable::Never),
                                 false));
             }
         }
@@ -5171,6 +5266,7 @@ impl<'a> Resolver<'a> {
                             let id = import_resolution.id(namespace);
                             // track imports and extern crates as well
                             self.used_imports.insert((id, namespace));
+                            self.record_import_use(id, name);
                             match target.target_module.def_id.get() {
                                 Some(DefId{krate: kid, ..}) => {
                                     self.used_crates.insert(kid);
@@ -5859,7 +5955,10 @@ impl<'a> Resolver<'a> {
                 };
                 if self.trait_item_map.contains_key(&(name, did)) {
                     add_trait_info(&mut found_traits, did, name);
-                    self.used_imports.insert((import.type_id, TypeNS));
+                    let id = import.type_id;
+                    self.used_imports.insert((id, TypeNS));
+                    let trait_name = self.get_trait_name(did);
+                    self.record_import_use(id, trait_name);
                     if let Some(DefId{krate: kid, ..}) = target.target_module.def_id.get() {
                         self.used_crates.insert(kid);
                     }
@@ -5993,14 +6092,23 @@ pub struct CrateMap {
     pub trait_map: TraitMap,
     pub external_exports: ExternalExports,
     pub last_private_map: LastPrivateMap,
+    pub glob_map: Option<GlobMap>
+}
+
+#[deriving(PartialEq,Copy)]
+pub enum MakeGlobMap {
+    Yes,
+    No
 }
 
 /// Entry point to crate resolution.
-pub fn resolve_crate(session: &Session,
-                     _: &LanguageItems,
-                     krate: &Crate)
-                  -> CrateMap {
-    let mut resolver = Resolver::new(session, krate.span);
+pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
+                               ast_map: &'a ast_map::Map<'tcx>,
+                               _: &LanguageItems,
+                               krate: &Crate,
+                               make_glob_map: MakeGlobMap)
+                               -> CrateMap {
+    let mut resolver = Resolver::new(session, ast_map, krate.span, make_glob_map);
 
     resolver.build_reduced_graph(krate);
     session.abort_if_errors();
@@ -6024,5 +6132,10 @@ pub fn resolve_crate(session: &Session,
         trait_map: resolver.trait_map,
         external_exports: resolver.external_exports,
         last_private_map: resolver.last_private,
+        glob_map: if resolver.make_glob_map {
+                        Some(resolver.glob_map)
+                    } else {
+                        None
+                    },
     }
 }
diff --git a/src/librustc_resolve/record_exports.rs b/src/librustc_resolve/record_exports.rs
index 41882a94b34..80659152f9f 100644
--- a/src/librustc_resolve/record_exports.rs
+++ b/src/librustc_resolve/record_exports.rs
@@ -27,24 +27,24 @@ use syntax::parse::token;
 
 use std::rc::Rc;
 
-struct ExportRecorder<'a, 'b:'a> {
-    resolver: &'a mut Resolver<'b>
+struct ExportRecorder<'a, 'b:'a, 'tcx:'b> {
+    resolver: &'a mut Resolver<'b, 'tcx>
 }
 
 // Deref and DerefMut impls allow treating ExportRecorder as Resolver.
-impl<'a, 'b> Deref<Resolver<'b>> for ExportRecorder<'a, 'b> {
-    fn deref<'c>(&'c self) -> &'c Resolver<'b> {
+impl<'a, 'b, 'tcx:'b> Deref<Resolver<'b, 'tcx>> for ExportRecorder<'a, 'b, 'tcx> {
+    fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> {
         &*self.resolver
     }
 }
 
-impl<'a, 'b> DerefMut<Resolver<'b>> for ExportRecorder<'a, 'b> {
-    fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> {
+impl<'a, 'b, 'tcx:'b> DerefMut<Resolver<'b, 'tcx>> for ExportRecorder<'a, 'b, 'tcx> {
+    fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> {
         &mut *self.resolver
     }
 }
 
-impl<'a, 'b> ExportRecorder<'a, 'b> {
+impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
     fn record_exports_for_module_subtree(&mut self,
                                          module_: Rc<Module>) {
         // If this isn't a local krate, then bail out. We don't need to record
diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs
index 0183aa8c2aa..f491bc84b62 100644
--- a/src/librustc_trans/save/mod.rs
+++ b/src/librustc_trans/save/mod.rs
@@ -1197,7 +1197,28 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                                                self.cur_scope);
                         self.write_sub_paths_truncated(path);
                     }
-                    ast::ViewPathGlob(ref path, _) => {
+                    ast::ViewPathGlob(ref path, id) => {
+                        // Make a comma-separated list of names of imported modules.
+                        let mut name_string = String::new();
+                        let glob_map = &self.analysis.glob_map;
+                        let glob_map = glob_map.as_ref().unwrap();
+                        if glob_map.contains_key(&id) {
+                            let names = glob_map.index(&id);
+                            for n in names.iter() {
+                                if name_string.len() > 0 {
+                                    name_string.push_str(", ");
+                                }
+                                name_string.push_str(n.as_str());
+                            }
+                        }
+
+                        let sub_span = self.span.sub_span_of_token(path.span,
+                                                                   token::BinOp(token::Star));
+                        self.fmt.use_glob_str(path.span,
+                                              sub_span,
+                                              id,
+                                              name_string.as_slice(),
+                                              self.cur_scope);
                         self.write_sub_paths(path);
                     }
                     ast::ViewPathList(ref path, ref list, _) => {
@@ -1482,6 +1503,7 @@ pub fn process_crate(sess: &Session,
         return;
     }
 
+    assert!(analysis.glob_map.is_some());
     let cratename = match attr::find_crate_name(krate.attrs[]) {
         Some(name) => name.get().to_string(),
         None => {
diff --git a/src/librustc_trans/save/recorder.rs b/src/librustc_trans/save/recorder.rs
index 08670864ade..b2dd9218f17 100644
--- a/src/librustc_trans/save/recorder.rs
+++ b/src/librustc_trans/save/recorder.rs
@@ -74,6 +74,7 @@ pub enum Row {
     Impl,
     Module,
     UseAlias,
+    UseGlob,
     ExternCrate,
     Inheritance,
     MethodCall,
@@ -125,6 +126,7 @@ impl<'a> FmtStrs<'a> {
             UseAlias => ("use_alias",
                          vec!("id","refid","refidcrate","name","scopeid"),
                          true, true),
+            UseGlob => ("use_glob", vec!("id","value","scopeid"), true, true),
             ExternCrate => ("extern_crate",
                             vec!("id","name","location","crate","scopeid"),
                             true, true),
@@ -480,6 +482,18 @@ impl<'a> FmtStrs<'a> {
                               svec!(id, mod_node, mod_crate, name, parent));
     }
 
+    pub fn use_glob_str(&mut self,
+                        span: Span,
+                        sub_span: Option<Span>,
+                        id: NodeId,
+                        values: &str,
+                        parent: NodeId) {
+        self.check_and_record(UseGlob,
+                              span,
+                              sub_span,
+                              svec!(id, values, parent));
+    }
+
     pub fn extern_crate_str(&mut self,
                           span: Span,
                           sub_span: Option<Span>,
diff --git a/src/librustc_trans/save/span_utils.rs b/src/librustc_trans/save/span_utils.rs
index a92d3c06e64..e9d862d3781 100644
--- a/src/librustc_trans/save/span_utils.rs
+++ b/src/librustc_trans/save/span_utils.rs
@@ -280,6 +280,19 @@ impl<'a> SpanUtils<'a> {
         }
     }
 
+    pub fn sub_span_of_token(&self, span: Span, tok: Token) -> Option<Span> {
+        let mut toks = self.retokenise_span(span);
+        loop {
+            let next = toks.real_token();
+            if next.tok == token::Eof {
+                return None;
+            }
+            if next.tok == tok {
+                return self.make_sub_span(span, Some(next.sp));
+            }
+        }
+    }
+
     pub fn sub_span_after_keyword(&self,
                               span: Span,
                               keyword: keywords::Keyword) -> Option<Span> {
diff --git a/src/librustc_trans/trans/mod.rs b/src/librustc_trans/trans/mod.rs
index 05797d74fee..4b1b92b552c 100644
--- a/src/librustc_trans/trans/mod.rs
+++ b/src/librustc_trans/trans/mod.rs
@@ -69,4 +69,3 @@ pub struct CrateTranslation {
     pub crate_formats: dependency_format::Dependencies,
     pub no_builtins: bool,
 }
-
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index 6c213555ce4..072ac89c7c8 100644
--- a/src/libstd/ascii.rs
+++ b/src/libstd/ascii.rs
@@ -630,8 +630,8 @@ static ASCII_UPPER_MAP: [u8, ..256] = [
 
 #[cfg(test)]
 mod tests {
-    use prelude::*;
     use super::*;
+    use prelude::*;
     use char::from_u32;
 
     macro_rules! v2ascii {
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs
index fb44961017f..fb369924c64 100644
--- a/src/libstd/c_str.rs
+++ b/src/libstd/c_str.rs
@@ -534,13 +534,12 @@ pub unsafe fn from_c_multistring<F>(buf: *const libc::c_char,
 
 #[cfg(test)]
 mod tests {
+    use super::*;
     use prelude::*;
     use ptr;
     use thread::Thread;
     use libc;
 
-    use super::*;
-
     #[test]
     fn test_str_multistring_parsing() {
         unsafe {
diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs
index 7352cdfbfe7..d3bfaab83da 100644
--- a/src/libstd/comm/mod.rs
+++ b/src/libstd/comm/mod.rs
@@ -333,12 +333,10 @@ macro_rules! test {
         mod $name {
             #![allow(unused_imports)]
 
-            use prelude::*;
-            use rt;
-
-            use comm::*;
             use super::*;
+            use comm::*;
             use thread::Thread;
+            use prelude::*;
 
             $(#[$a])* #[test] fn f() { $b }
         }
@@ -1022,10 +1020,9 @@ impl<T: Send> Drop for Receiver<T> {
 
 #[cfg(test)]
 mod test {
+    use super::*;
     use prelude::*;
-
     use os;
-    use super::*;
 
     pub fn stress_factor() -> uint {
         match os::getenv("RUST_TEST_STRESS") {
diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs
index 431e11cf9ca..01151059530 100644
--- a/src/libstd/io/mem.rs
+++ b/src/libstd/io/mem.rs
@@ -399,9 +399,9 @@ impl<'a> Buffer for BufReader<'a> {
 #[cfg(test)]
 mod test {
     extern crate "test" as test_crate;
-    use prelude::*;
     use super::*;
     use io::*;
+    use prelude::*;
     use io;
     use self::test_crate::Bencher;
 
diff --git a/src/libstd/io/net/pipe.rs b/src/libstd/io/net/pipe.rs
index 01eb33b44f9..4afc72cde71 100644
--- a/src/libstd/io/net/pipe.rs
+++ b/src/libstd/io/net/pipe.rs
@@ -266,10 +266,10 @@ impl sys_common::AsInner<UnixAcceptorImp> for UnixAcceptor {
 #[cfg(test)]
 #[allow(experimental)]
 mod tests {
-    use prelude::*;
     use super::*;
     use io::*;
     use io::test::*;
+    use prelude::*;
     use io::fs::PathExtensions;
     use time::Duration;
 
diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs
index f462143faf4..a36703172c3 100644
--- a/src/libstd/io/net/udp.rs
+++ b/src/libstd/io/net/udp.rs
@@ -249,10 +249,10 @@ impl Writer for UdpStream {
 #[allow(experimental)]
 mod test {
     use super::*;
-    use prelude::*;
-    use io::*;
     use io::net::ip::*;
+    use io::*;
     use io::test::*;
+    use prelude::*;
 
     // FIXME #11530 this fails on android because tests are run as root
     #[cfg_attr(any(windows, target_os = "android"), ignore)]
diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs
index 4a0a3936424..93aa627ffba 100644
--- a/src/libstd/io/process.rs
+++ b/src/libstd/io/process.rs
@@ -744,9 +744,9 @@ mod tests {
     #![allow(unused_imports)]
 
     use super::*;
-    use prelude::*;
     use io::timer::*;
     use io::*;
+    use prelude::*;
     use io::fs::PathExtensions;
     use time::Duration;
     use str;
diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs
index f0a00b421c3..d941665f048 100644
--- a/src/libstd/path/posix.rs
+++ b/src/libstd/path/posix.rs
@@ -447,8 +447,10 @@ static dot_dot_static: &'static [u8] = b"..";
 
 #[cfg(test)]
 mod tests {
-    use prelude::*;
     use super::*;
+    use prelude::Option::{mod, Some, None};
+    use prelude::{Vec, Clone, AsSlice, SliceExt, CloneSliceExt, IteratorExt};
+    use prelude::{DoubleEndedIteratorExt, Str, StrExt, ToString, GenericPath};
     use str;
 
     macro_rules! t {
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
index 7d10188c437..12da1752adf 100644
--- a/src/libstd/path/windows.rs
+++ b/src/libstd/path/windows.rs
@@ -1121,8 +1121,10 @@ fn prefix_len(p: Option<PathPrefix>) -> uint {
 
 #[cfg(test)]
 mod tests {
-    use prelude::*;
     use super::*;
+    use prelude::Option::{mod, Some, None};
+    use prelude::{Vec, Clone, AsSlice, SliceExt, CloneSliceExt, IteratorExt};
+    use prelude::{DoubleEndedIteratorExt, Str, ToString, GenericPath};
     use super::PathPrefix::*;
     use super::parse_prefix;