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?
This commit is contained in:
bors 2014-12-27 00:48:41 +00:00
commit 3c60bc02ce
27 changed files with 287 additions and 98 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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,
{

View File

@ -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;

View File

@ -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::*;

View File

@ -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;

View File

@ -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;

View File

@ -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|

View File

@ -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);

View File

@ -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

View File

@ -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
},
}
}

View File

@ -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

View File

@ -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 => {

View File

@ -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>,

View File

@ -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> {

View File

@ -69,4 +69,3 @@ pub struct CrateTranslation {
pub crate_formats: dependency_format::Dependencies,
pub no_builtins: bool,
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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 prelude::*;
use os;
use super::*;
use prelude::*;
use os;
pub fn stress_factor() -> uint {
match os::getenv("RUST_TEST_STRESS") {

View File

@ -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;

View File

@ -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;

View File

@ -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)]

View File

@ -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;

View File

@ -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 {

View File

@ -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;