From df0c6d93852c51b6936d4b72b6b4be5f1932fb8a Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 23 Nov 2014 22:29:41 +1300 Subject: [PATCH 1/3] save-analysis: emit names of items that a glob import actually imports. There is also some work here to make resolve a bit more stable - it no longer overwrites a specific import with a glob import. [breaking-change] Import shadowing of single/list imports by globs is now forbidden. An interesting case is where a glob import imports a re-export (`pub use`) of a single import. This still counts as a single import for the purposes of shadowing .You can usually fix any bustage by re-ordering such imports. A single import may still shadow (override) a glob import or the prelude. --- src/librustc/metadata/csearch.rs | 7 + src/librustc/metadata/decoder.rs | 8 + src/librustc/middle/ty.rs | 1 + src/librustc_driver/driver.rs | 20 ++- src/librustc_driver/test.rs | 2 +- src/librustc_resolve/check_unused.rs | 14 +- src/librustc_resolve/lib.rs | 229 ++++++++++++++++++++------ src/librustc_trans/save/mod.rs | 24 ++- src/librustc_trans/save/recorder.rs | 14 ++ src/librustc_trans/save/span_utils.rs | 13 ++ src/librustc_trans/trans/mod.rs | 1 - 11 files changed, 270 insertions(+), 63 deletions(-) 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, + 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 9c1259f4120..79e24ad56e4 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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)] diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 20bb9c2f4fd..c727bea4c2c 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -342,17 +342,24 @@ 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 resolve::CrateMap { + let make_glob_map = match save_analysis(&sess) { + true => middle::resolve::MakeGlobMap::Yes, + false => middle::resolve::MakeGlobMap::No, + }; def_map, freevars, capture_mode_map, 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, + &lang_items, + krate, + make_glob_map)); // Discard MTWT tables that aren't required past resolution. syntax::ext::mtwt::clear_tables(); @@ -454,14 +461,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 526bbca8d70..1ef1486dd54 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 39cdf6fc8f3..c09014cdb7a 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -28,19 +28,19 @@ 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> Deref> for UnusedImportCheckVisitor<'a, 'b, 'tcx:'b> { + 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> DerefMut> for UnusedImportCheckVisitor<'a, 'b, 'tcx:'b> { + fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> { &mut *self.resolver } } @@ -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..815a8400a37 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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; @@ -109,6 +110,10 @@ struct BindingInfo { // Map from the name in a pattern to its binding mode. type BindingMap = HashMap; +// Map from the NodeId of a glob import to a list of items which are actually +// imported. +pub type GlobMap = HashMap>; + #[deriving(Copy, PartialEq)] enum PatternBindingMode { RefutableMode, @@ -168,7 +173,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 +345,16 @@ impl Rib { } } +/// Whether an import can be shadowed by another import. +#[deriving(Show,PartialEq,Clone)] +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 +362,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 +371,7 @@ impl ImportDirective { span: Span, id: NodeId, is_public: bool, - shadowable: bool) + shadowable: Shadowable) -> ImportDirective { ImportDirective { module_path: module_path, @@ -374,13 +389,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 +457,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 +866,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 +921,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()); @@ -939,6 +970,20 @@ impl<'a, 'b, 'v> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b> { } +<<<<<<< HEAD:src/librustc_resolve/lib.rs +======= +struct UnusedImportCheckVisitor<'a, 'b:'a, 'tcx:'b> { + resolver: &'a mut Resolver<'b, 'tcx> +} + +impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { + fn visit_view_item(&mut self, vi: &ViewItem) { + self.resolver.check_for_item_unused_imports(vi); + visit::walk_view_item(self, vi); + } +} + +>>>>>>> save-analysis: emit names of items that a glob import actually imports.:src/librustc/middle/resolve.rs #[deriving(PartialEq)] enum FallbackChecks { Everything, @@ -946,8 +991,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 +1010,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 +1047,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 +1662,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 +1737,11 @@ impl<'a> Resolver<'a> { view_path.span, id, is_public, - shadowable); + if shadowable == Shadowable::Never { + Shadowable::Glob + } else { + shadowable + }); } } } @@ -2131,7 +2192,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 +2387,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 +2422,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 +2609,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 +2634,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 +2649,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 +2841,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 +2972,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 +2990,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 +3038,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 +3081,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 +3103,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 +3119,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 +3452,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 +3474,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 +3491,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 +3717,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 +3754,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 +3772,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 +5284,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 +5973,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 +6110,23 @@ pub struct CrateMap { pub trait_map: TraitMap, pub external_exports: ExternalExports, pub last_private_map: LastPrivateMap, + pub glob_map: Option +} + +#[deriving(PartialEq)] +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 +6150,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_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, + 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 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 { + 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 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, } - From dbde7419cc120d97e520063682751dfc3a901fb5 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 28 Nov 2014 16:02:33 +1300 Subject: [PATCH 2/3] Fix fallout --- src/libgraphviz/maybe_owned_vec.rs | 1 - src/librustc_borrowck/borrowck/check_loans.rs | 2 -- .../borrowck/gather_loans/gather_moves.rs | 1 - src/librustc_borrowck/borrowck/gather_loans/mod.rs | 1 - .../borrowck/gather_loans/restrictions.rs | 2 -- src/librustc_driver/driver.rs | 7 ++++--- src/librustc_resolve/lib.rs | 4 ++-- src/libstd/ascii.rs | 2 +- src/libstd/comm/mod.rs | 11 ++++------- src/libstd/io/mem.rs | 2 +- src/libstd/io/net/pipe.rs | 2 +- src/libstd/io/net/udp.rs | 4 ++-- src/libstd/io/process.rs | 2 +- src/libstd/path/posix.rs | 2 +- src/libstd/path/windows.rs | 2 +- 15 files changed, 18 insertions(+), 27 deletions(-) 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_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 c727bea4c2c..f132ede06a4 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -342,9 +342,10 @@ 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 = match save_analysis(&sess) { - true => middle::resolve::MakeGlobMap::Yes, - false => middle::resolve::MakeGlobMap::No, + let make_glob_map = if save_analysis(&sess) { + middle::resolve::MakeGlobMap::Yes + } else { + middle::resolve::MakeGlobMap::No }; def_map, freevars, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 815a8400a37..03e992ef7a7 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -346,7 +346,7 @@ impl Rib { } /// Whether an import can be shadowed by another import. -#[deriving(Show,PartialEq,Clone)] +#[deriving(Show,PartialEq,Clone,Copy)] enum Shadowable { Always, /// Means that the recorded import obeys the glob shadowing rules, i.e., can @@ -6113,7 +6113,7 @@ pub struct CrateMap { pub glob_map: Option } -#[deriving(PartialEq)] +#[deriving(PartialEq,Copy)] pub enum MakeGlobMap { Yes, No 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/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 Drop for Receiver { #[cfg(test)] mod test { - use prelude::*; - - use os; use super::*; + use prelude::*; + use os; 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 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..c72e41d61c0 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -447,8 +447,8 @@ static dot_dot_static: &'static [u8] = b".."; #[cfg(test)] mod tests { - use prelude::*; use super::*; + use prelude::*; use str; macro_rules! t { diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 7d10188c437..278908b8068 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -1121,7 +1121,7 @@ fn prefix_len(p: Option) -> uint { #[cfg(test)] mod tests { - use prelude::*; + use mem; use super::*; use super::PathPrefix::*; use super::parse_prefix; From 4b92a5a229ebe7635851fc7bad94108f9de8dcc6 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 26 Dec 2014 11:01:16 +1300 Subject: [PATCH 3/3] Rebasing changes --- src/libcollections/str.rs | 2 +- src/librustc/middle/ty.rs | 8 ++++++-- src/librustc_driver/driver.rs | 6 ++++-- src/librustc_resolve/check_unused.rs | 6 +++--- src/librustc_resolve/lib.rs | 22 ++-------------------- src/librustc_resolve/record_exports.rs | 14 +++++++------- src/libstd/c_str.rs | 3 +-- src/libstd/path/posix.rs | 4 +++- src/libstd/path/windows.rs | 4 +++- 9 files changed, 30 insertions(+), 39 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/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 79e24ad56e4..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,7 +105,7 @@ pub struct CrateAnalysis<'tcx> { pub ty_cx: ty::ctxt<'tcx>, pub reachable: NodeSet, pub name: String, - pub glob_map: Option, + pub glob_map: Option, } #[deriving(Copy, PartialEq, Eq, Hash)] @@ -6286,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_driver/driver.rs b/src/librustc_driver/driver.rs index f132ede06a4..4ab5c19430b 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -343,10 +343,11 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, middle::lang_items::collect_language_items(krate, &sess)); let make_glob_map = if save_analysis(&sess) { - middle::resolve::MakeGlobMap::Yes + resolve::MakeGlobMap::Yes } else { - middle::resolve::MakeGlobMap::No + resolve::MakeGlobMap::No }; + let resolve::CrateMap { def_map, freevars, capture_mode_map, @@ -358,6 +359,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, } = time(time_passes, "resolution", (), |_| resolve::resolve_crate(&sess, + &ast_map, &lang_items, krate, make_glob_map)); diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index c09014cdb7a..78527315199 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -33,19 +33,19 @@ struct UnusedImportCheckVisitor<'a, 'b:'a, 'tcx:'b> { } // Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver. -impl<'a, 'b, 'tcx> Deref> for UnusedImportCheckVisitor<'a, 'b, 'tcx:'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, 'tcx> DerefMut> for UnusedImportCheckVisitor<'a, 'b, 'tcx:'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 diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 03e992ef7a7..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}; @@ -110,10 +110,6 @@ struct BindingInfo { // Map from the name in a pattern to its binding mode. type BindingMap = HashMap; -// Map from the NodeId of a glob import to a list of items which are actually -// imported. -pub type GlobMap = HashMap>; - #[deriving(Copy, PartialEq)] enum PatternBindingMode { RefutableMode, @@ -970,20 +966,6 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } -<<<<<<< HEAD:src/librustc_resolve/lib.rs -======= -struct UnusedImportCheckVisitor<'a, 'b:'a, 'tcx:'b> { - resolver: &'a mut Resolver<'b, 'tcx> -} - -impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { - fn visit_view_item(&mut self, vi: &ViewItem) { - self.resolver.check_for_item_unused_imports(vi); - visit::walk_view_item(self, vi); - } -} - ->>>>>>> save-analysis: emit names of items that a glob import actually imports.:src/librustc/middle/resolve.rs #[deriving(PartialEq)] enum FallbackChecks { Everything, 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> 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/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(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/path/posix.rs b/src/libstd/path/posix.rs index c72e41d61c0..d941665f048 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -448,7 +448,9 @@ static dot_dot_static: &'static [u8] = b".."; #[cfg(test)] mod tests { use super::*; - use prelude::*; + 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 278908b8068..12da1752adf 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 mem; 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;