mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-02 11:44:28 +00:00
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:
commit
3c60bc02ce
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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::*;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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|
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 => {
|
||||
|
@ -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>,
|
||||
|
@ -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> {
|
||||
|
@ -69,4 +69,3 @@ pub struct CrateTranslation {
|
||||
pub crate_formats: dependency_format::Dependencies,
|
||||
pub no_builtins: bool,
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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") {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user