diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 5feae5e558edf..bccd2a1198a4b 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 88483b6c93543..ddda2b38c223a 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 13342bf82cfea..51cebbfb52c58 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 f05607a999b66..ee928828827b7 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, + 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, cdata: Cmd, id: ast::NodeId) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 9c1259f41202e..c0d5d6b11cf7e 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, } #[deriving(Copy, PartialEq, Eq, Hash)] @@ -6285,6 +6286,10 @@ pub type CaptureModeMap = NodeMap; // Trait method resolution pub type TraitMap = NodeMap>; +// Map from the NodeId of a glob import to a list of items which are actually +// imported. +pub type GlobMap = HashMap>; + pub fn with_freevars(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 568bb023b68a2..046b9547cbbc5 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 01cbab6dbf42e..85cc691fb9db9 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 d7f50ccc6ba3c..c0e892cdd2798 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 c783489dab720..fc15c0eb4ec97 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 20bb9c2f4fd1c..4ab5c19430b5c 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) { - 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 526bbca8d70dd..1ef1486dd54d2 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -123,7 +123,7 @@ fn test_env(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 39cdf6fc8f318..78527315199ca 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> for UnusedImportCheckVisitor<'a, 'b> { - fn deref<'c>(&'c self) -> &'c Resolver<'b> { +impl<'a, 'b, 'tcx:'b> Deref> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { + fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> { &*self.resolver } } -impl<'a, 'b> DerefMut> for UnusedImportCheckVisitor<'a, 'b> { - fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> { +impl<'a, 'b, 'tcx:'b> DerefMut> 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 bf9e9294307ef..720883a8e9a54 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, @@ -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, bindings: Rc, - shadowable: bool, + shadowable: Shadowable, } impl Target { fn new(target_module: Rc, bindings: Rc, - 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, } -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 +} + +#[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 41882a94b34fd..80659152f9fc7 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> for ExportRecorder<'a, 'b> { - fn deref<'c>(&'c self) -> &'c Resolver<'b> { +impl<'a, 'b, 'tcx:'b> Deref> for ExportRecorder<'a, 'b, 'tcx> { + fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> { &*self.resolver } } -impl<'a, 'b> DerefMut> for ExportRecorder<'a, 'b> { - fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> { +impl<'a, 'b, 'tcx:'b> DerefMut> 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) { // 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 0183aa8c2aabb..f491bc84b62c4 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 08670864ade93..b2dd9218f1797 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, + 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, diff --git a/src/librustc_trans/save/span_utils.rs b/src/librustc_trans/save/span_utils.rs index a92d3c06e64fb..e9d862d3781bb 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 { + 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 { diff --git a/src/librustc_trans/trans/mod.rs b/src/librustc_trans/trans/mod.rs index 05797d74feefc..4b1b92b552cec 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 6c213555ce496..072ac89c7c823 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 fb44961017fcd..fb369924c64b1 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -534,13 +534,12 @@ pub unsafe fn from_c_multistring(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 7352cdfbfe7f8..d3bfaab83da48 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 Drop for Receiver { #[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 431e11cf9caca..01151059530f0 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 01eb33b44f92f..4afc72cde711e 100644 --- a/src/libstd/io/net/pipe.rs +++ b/src/libstd/io/net/pipe.rs @@ -266,10 +266,10 @@ impl sys_common::AsInner 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 f462143faf4c1..a36703172c3ca 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 4a0a393642439..93aa627ffba13 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 f0a00b421c3a3..d941665f0482f 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 7d10188c437e2..12da1752adf9c 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -1121,8 +1121,10 @@ fn prefix_len(p: Option) -> 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;