auto merge of #19995 : eddyb/rust/split-resolve, r=nikomatsakis
r? @nikomatsakis
This commit is contained in:
commit
8443b09e36
23 changed files with 565 additions and 475 deletions
12
mk/crates.mk
12
mk/crates.mk
|
@ -53,7 +53,8 @@ TARGET_CRATES := libc std flate arena term \
|
|||
serialize getopts collections test time rand \
|
||||
log regex graphviz core rbml alloc \
|
||||
unicode
|
||||
RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_driver rustc_trans rustc_back rustc_llvm
|
||||
RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_resolve rustc_driver \
|
||||
rustc_trans rustc_back rustc_llvm
|
||||
HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc regex_macros fmt_macros
|
||||
CRATES := $(TARGET_CRATES) $(HOST_CRATES)
|
||||
TOOLS := compiletest rustdoc rustc
|
||||
|
@ -67,11 +68,12 @@ DEPS_std := core libc rand alloc collections unicode \
|
|||
DEPS_graphviz := std
|
||||
DEPS_syntax := std term serialize log fmt_macros arena libc
|
||||
DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \
|
||||
rustc_typeck log syntax serialize rustc_llvm rustc_trans
|
||||
rustc_typeck rustc_resolve log syntax serialize rustc_llvm rustc_trans
|
||||
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
|
||||
log syntax serialize rustc_llvm
|
||||
DEPS_rustc_typeck := rustc syntax
|
||||
DEPS_rustc_borrowck := rustc log graphviz syntax
|
||||
DEPS_rustc_resolve := rustc log syntax
|
||||
DEPS_rustc := syntax flate arena serialize getopts rbml \
|
||||
time log graphviz rustc_llvm rustc_back
|
||||
DEPS_rustc_llvm := native:rustllvm libc std
|
||||
|
@ -118,9 +120,11 @@ DOC_CRATES := $(filter-out rustc, \
|
|||
$(filter-out rustc_trans, \
|
||||
$(filter-out rustc_typeck, \
|
||||
$(filter-out rustc_borrowck, \
|
||||
$(filter-out rustc_resolve, \
|
||||
$(filter-out rustc_driver, \
|
||||
$(filter-out syntax, $(CRATES)))))))
|
||||
COMPILER_DOC_CRATES := rustc rustc_trans rustc_borrowck rustc_typeck rustc_driver syntax
|
||||
$(filter-out syntax, $(CRATES))))))))
|
||||
COMPILER_DOC_CRATES := rustc rustc_trans rustc_borrowck rustc_resolve \
|
||||
rustc_typeck rustc_driver syntax
|
||||
|
||||
# This macro creates some simple definitions for each crate being built, just
|
||||
# some munging of all of the parameters above.
|
||||
|
|
|
@ -21,7 +21,8 @@ $(eval $(call RUST_CRATE,coretest))
|
|||
|
||||
TEST_TARGET_CRATES = $(filter-out core unicode,$(TARGET_CRATES)) coretest
|
||||
TEST_DOC_CRATES = $(DOC_CRATES)
|
||||
TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_trans,$(HOST_CRATES))
|
||||
TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve rustc_trans,\
|
||||
$(HOST_CRATES))
|
||||
TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES)
|
||||
|
||||
######################################################################
|
||||
|
|
|
@ -90,7 +90,6 @@ pub mod middle {
|
|||
pub mod reachable;
|
||||
pub mod region;
|
||||
pub mod recursion_limit;
|
||||
pub mod resolve;
|
||||
pub mod resolve_lifetime;
|
||||
pub mod stability;
|
||||
pub mod subst;
|
||||
|
|
|
@ -19,7 +19,6 @@ use metadata::cstore;
|
|||
use metadata::decoder;
|
||||
use middle::def;
|
||||
use middle::lang_items;
|
||||
use middle::resolve;
|
||||
use middle::ty;
|
||||
|
||||
use rbml;
|
||||
|
@ -148,7 +147,7 @@ pub fn get_impl_or_trait_item<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId)
|
|||
}
|
||||
|
||||
pub fn get_trait_item_name_and_kind(cstore: &cstore::CStore, def: ast::DefId)
|
||||
-> (ast::Name, resolve::TraitItemKind) {
|
||||
-> (ast::Name, def::TraitItemKind) {
|
||||
let cdata = cstore.get_crate_data(def.krate);
|
||||
decoder::get_trait_item_name_and_kind(cstore.intr.clone(),
|
||||
&*cdata,
|
||||
|
|
|
@ -27,7 +27,6 @@ use metadata::tydecode::{parse_ty_data, parse_region_data, parse_def_id,
|
|||
parse_predicate_data};
|
||||
use middle::def;
|
||||
use middle::lang_items;
|
||||
use middle::resolve::{TraitItemKind, TypeTraitItemKind};
|
||||
use middle::subst;
|
||||
use middle::ty::{ImplContainer, TraitContainer};
|
||||
use middle::ty::{mod, Ty};
|
||||
|
@ -785,15 +784,15 @@ pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
|
|||
pub fn get_trait_item_name_and_kind(intr: Rc<IdentInterner>,
|
||||
cdata: Cmd,
|
||||
id: ast::NodeId)
|
||||
-> (ast::Name, TraitItemKind) {
|
||||
-> (ast::Name, def::TraitItemKind) {
|
||||
let doc = lookup_item(id, cdata.data());
|
||||
let name = item_name(&*intr, doc);
|
||||
match item_sort(doc) {
|
||||
'r' | 'p' => {
|
||||
let explicit_self = get_explicit_self(doc);
|
||||
(name, TraitItemKind::from_explicit_self_category(explicit_self))
|
||||
(name, def::TraitItemKind::from_explicit_self_category(explicit_self))
|
||||
}
|
||||
't' => (name, TypeTraitItemKind),
|
||||
't' => (name, def::TypeTraitItemKind),
|
||||
c => {
|
||||
panic!("get_trait_item_name_and_kind(): unknown trait item kind \
|
||||
in metadata: `{}`", c)
|
||||
|
|
|
@ -21,10 +21,10 @@ use metadata::common::*;
|
|||
use metadata::cstore;
|
||||
use metadata::decoder;
|
||||
use metadata::tyencode;
|
||||
use middle::def;
|
||||
use middle::ty::{lookup_item_type};
|
||||
use middle::ty::{mod, Ty};
|
||||
use middle::stability;
|
||||
use middle;
|
||||
use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
|
||||
|
||||
use serialize::Encodable;
|
||||
|
@ -66,7 +66,7 @@ pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
|
|||
pub struct EncodeParams<'a, 'tcx: 'a> {
|
||||
pub diag: &'a SpanHandler,
|
||||
pub tcx: &'a ty::ctxt<'tcx>,
|
||||
pub reexports2: &'a middle::resolve::ExportMap2,
|
||||
pub reexports: &'a def::ExportMap,
|
||||
pub item_symbols: &'a RefCell<NodeMap<String>>,
|
||||
pub link_meta: &'a LinkMeta,
|
||||
pub cstore: &'a cstore::CStore,
|
||||
|
@ -77,7 +77,7 @@ pub struct EncodeParams<'a, 'tcx: 'a> {
|
|||
pub struct EncodeContext<'a, 'tcx: 'a> {
|
||||
pub diag: &'a SpanHandler,
|
||||
pub tcx: &'a ty::ctxt<'tcx>,
|
||||
pub reexports2: &'a middle::resolve::ExportMap2,
|
||||
pub reexports: &'a def::ExportMap,
|
||||
pub item_symbols: &'a RefCell<NodeMap<String>>,
|
||||
pub link_meta: &'a LinkMeta,
|
||||
pub cstore: &'a cstore::CStore,
|
||||
|
@ -379,7 +379,7 @@ fn encode_path<PI: Iterator<PathElem>>(rbml_w: &mut Encoder, path: PI) {
|
|||
}
|
||||
|
||||
fn encode_reexported_static_method(rbml_w: &mut Encoder,
|
||||
exp: &middle::resolve::Export2,
|
||||
exp: &def::Export,
|
||||
method_def_id: DefId,
|
||||
method_name: ast::Name) {
|
||||
debug!("(encode reexported static method) {}::{}",
|
||||
|
@ -398,7 +398,7 @@ fn encode_reexported_static_method(rbml_w: &mut Encoder,
|
|||
|
||||
fn encode_reexported_static_base_methods(ecx: &EncodeContext,
|
||||
rbml_w: &mut Encoder,
|
||||
exp: &middle::resolve::Export2)
|
||||
exp: &def::Export)
|
||||
-> bool {
|
||||
let impl_items = ecx.tcx.impl_items.borrow();
|
||||
match ecx.tcx.inherent_impls.borrow().get(&exp.def_id) {
|
||||
|
@ -428,7 +428,7 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
|
|||
|
||||
fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
|
||||
rbml_w: &mut Encoder,
|
||||
exp: &middle::resolve::Export2)
|
||||
exp: &def::Export)
|
||||
-> bool {
|
||||
match ecx.tcx.trait_items_cache.borrow().get(&exp.def_id) {
|
||||
Some(trait_items) => {
|
||||
|
@ -449,10 +449,8 @@ fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
|
|||
fn encode_reexported_static_methods(ecx: &EncodeContext,
|
||||
rbml_w: &mut Encoder,
|
||||
mod_path: PathElems,
|
||||
exp: &middle::resolve::Export2) {
|
||||
exp: &def::Export) {
|
||||
if let Some(ast_map::NodeItem(item)) = ecx.tcx.map.find(exp.def_id.node) {
|
||||
let original_name = token::get_ident(item.ident);
|
||||
|
||||
let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
|
||||
let (mut a, mut b) = (path, mod_path.clone());
|
||||
loop {
|
||||
|
@ -474,16 +472,16 @@ fn encode_reexported_static_methods(ecx: &EncodeContext,
|
|||
// encoded metadata for static methods relative to Bar,
|
||||
// but not yet for Foo.
|
||||
//
|
||||
if path_differs || original_name.get() != exp.name {
|
||||
if path_differs || item.ident.name != exp.name {
|
||||
if !encode_reexported_static_base_methods(ecx, rbml_w, exp) {
|
||||
if encode_reexported_static_trait_methods(ecx, rbml_w, exp) {
|
||||
debug!("(encode reexported static methods) {} [trait]",
|
||||
original_name);
|
||||
item.ident.name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug!("(encode reexported static methods) {} [base]",
|
||||
original_name);
|
||||
item.ident.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -519,7 +517,7 @@ fn encode_reexports(ecx: &EncodeContext,
|
|||
id: NodeId,
|
||||
path: PathElems) {
|
||||
debug!("(encoding info for module) encoding reexports for {}", id);
|
||||
match ecx.reexports2.get(&id) {
|
||||
match ecx.reexports.get(&id) {
|
||||
Some(ref exports) => {
|
||||
debug!("(encoding info for module) found reexports for {}", id);
|
||||
for exp in exports.iter() {
|
||||
|
@ -534,7 +532,7 @@ fn encode_reexports(ecx: &EncodeContext,
|
|||
rbml_w.wr_str(def_to_string(exp.def_id).as_slice());
|
||||
rbml_w.end_tag();
|
||||
rbml_w.start_tag(tag_items_data_item_reexport_name);
|
||||
rbml_w.wr_str(exp.name.as_slice());
|
||||
rbml_w.wr_str(exp.name.as_str());
|
||||
rbml_w.end_tag();
|
||||
rbml_w.end_tag();
|
||||
encode_reexported_static_methods(ecx, rbml_w, path.clone(), exp);
|
||||
|
@ -2071,7 +2069,7 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter,
|
|||
item_symbols,
|
||||
diag,
|
||||
tcx,
|
||||
reexports2,
|
||||
reexports,
|
||||
cstore,
|
||||
encode_inlined_item,
|
||||
link_meta,
|
||||
|
@ -2081,7 +2079,7 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter,
|
|||
let ecx = EncodeContext {
|
||||
diag: diag,
|
||||
tcx: tcx,
|
||||
reexports2: reexports2,
|
||||
reexports: reexports,
|
||||
item_symbols: item_symbols,
|
||||
link_meta: link_meta,
|
||||
cstore: cstore,
|
||||
|
|
|
@ -12,8 +12,7 @@
|
|||
// recursively.
|
||||
|
||||
use session::Session;
|
||||
use middle::resolve;
|
||||
use middle::def::{DefStatic, DefConst};
|
||||
use middle::def::{DefStatic, DefConst, DefMap};
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::{ast_util, ast_map};
|
||||
|
@ -22,7 +21,7 @@ use syntax::visit;
|
|||
|
||||
struct CheckCrateVisitor<'a, 'ast: 'a> {
|
||||
sess: &'a Session,
|
||||
def_map: &'a resolve::DefMap,
|
||||
def_map: &'a DefMap,
|
||||
ast_map: &'a ast_map::Map<'ast>
|
||||
}
|
||||
|
||||
|
@ -34,7 +33,7 @@ impl<'v, 'a, 'ast> Visitor<'v> for CheckCrateVisitor<'a, 'ast> {
|
|||
|
||||
pub fn check_crate<'ast>(sess: &Session,
|
||||
krate: &ast::Crate,
|
||||
def_map: &resolve::DefMap,
|
||||
def_map: &DefMap,
|
||||
ast_map: &ast_map::Map<'ast>) {
|
||||
let mut visitor = CheckCrateVisitor {
|
||||
sess: sess,
|
||||
|
@ -60,7 +59,7 @@ struct CheckItemRecursionVisitor<'a, 'ast: 'a> {
|
|||
root_it: &'a ast::Item,
|
||||
sess: &'a Session,
|
||||
ast_map: &'a ast_map::Map<'ast>,
|
||||
def_map: &'a resolve::DefMap,
|
||||
def_map: &'a DefMap,
|
||||
idstack: Vec<ast::NodeId>
|
||||
}
|
||||
|
||||
|
@ -68,7 +67,7 @@ struct CheckItemRecursionVisitor<'a, 'ast: 'a> {
|
|||
// FIXME: Should use the dependency graph when it's available (#1356)
|
||||
pub fn check_item_recursion<'a>(sess: &'a Session,
|
||||
ast_map: &'a ast_map::Map,
|
||||
def_map: &'a resolve::DefMap,
|
||||
def_map: &'a DefMap,
|
||||
it: &'a ast::Item) {
|
||||
|
||||
let mut visitor = CheckItemRecursionVisitor {
|
||||
|
|
|
@ -10,11 +10,16 @@
|
|||
|
||||
pub use self::Def::*;
|
||||
pub use self::MethodProvenance::*;
|
||||
pub use self::TraitItemKind::*;
|
||||
|
||||
use middle::subst::ParamSpace;
|
||||
use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory};
|
||||
use util::nodemap::NodeMap;
|
||||
use syntax::ast;
|
||||
use syntax::ast_util::local_def;
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub enum Def {
|
||||
DefFn(ast::DefId, bool /* is_ctor */),
|
||||
|
@ -56,6 +61,18 @@ pub enum Def {
|
|||
DefMethod(ast::DefId /* method */, Option<ast::DefId> /* trait */, MethodProvenance),
|
||||
}
|
||||
|
||||
// Definition mapping
|
||||
pub type DefMap = RefCell<NodeMap<Def>>;
|
||||
// This is the replacement export map. It maps a module to all of the exports
|
||||
// within.
|
||||
pub type ExportMap = NodeMap<Vec<Export>>;
|
||||
|
||||
#[deriving(Copy)]
|
||||
pub struct Export {
|
||||
pub name: ast::Name, // The name of the target.
|
||||
pub def_id: ast::DefId, // The definition of the target.
|
||||
}
|
||||
|
||||
#[deriving(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub enum MethodProvenance {
|
||||
FromTrait(ast::DefId),
|
||||
|
@ -88,6 +105,25 @@ impl TyParamProvenance {
|
|||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone, Copy, Eq, PartialEq)]
|
||||
pub enum TraitItemKind {
|
||||
NonstaticMethodTraitItemKind,
|
||||
StaticMethodTraitItemKind,
|
||||
TypeTraitItemKind,
|
||||
}
|
||||
|
||||
impl TraitItemKind {
|
||||
pub fn from_explicit_self_category(explicit_self_category:
|
||||
ExplicitSelfCategory)
|
||||
-> TraitItemKind {
|
||||
if explicit_self_category == StaticExplicitSelfCategory {
|
||||
StaticMethodTraitItemKind
|
||||
} else {
|
||||
NonstaticMethodTraitItemKind
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Def {
|
||||
pub fn def_id(&self) -> ast::DefId {
|
||||
match *self {
|
||||
|
@ -122,4 +158,3 @@ impl Def {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
// except according to those terms.
|
||||
|
||||
use middle::def::*;
|
||||
use middle::resolve;
|
||||
use middle::ty;
|
||||
use util::nodemap::FnvHashMap;
|
||||
|
||||
|
@ -21,7 +20,7 @@ pub type PatIdMap = FnvHashMap<ast::Ident, ast::NodeId>;
|
|||
|
||||
// This is used because same-named variables in alternative patterns need to
|
||||
// use the NodeId of their namesake in the first pattern.
|
||||
pub fn pat_id_map(dm: &resolve::DefMap, pat: &ast::Pat) -> PatIdMap {
|
||||
pub fn pat_id_map(dm: &DefMap, pat: &ast::Pat) -> PatIdMap {
|
||||
let mut map = FnvHashMap::new();
|
||||
pat_bindings(dm, pat, |_bm, p_id, _s, path1| {
|
||||
map.insert(path1.node, p_id);
|
||||
|
@ -29,7 +28,7 @@ pub fn pat_id_map(dm: &resolve::DefMap, pat: &ast::Pat) -> PatIdMap {
|
|||
map
|
||||
}
|
||||
|
||||
pub fn pat_is_refutable(dm: &resolve::DefMap, pat: &ast::Pat) -> bool {
|
||||
pub fn pat_is_refutable(dm: &DefMap, pat: &ast::Pat) -> bool {
|
||||
match pat.node {
|
||||
ast::PatLit(_) | ast::PatRange(_, _) => true,
|
||||
ast::PatEnum(_, _) |
|
||||
|
@ -45,7 +44,7 @@ pub fn pat_is_refutable(dm: &resolve::DefMap, pat: &ast::Pat) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pat_is_variant_or_struct(dm: &resolve::DefMap, pat: &ast::Pat) -> bool {
|
||||
pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &ast::Pat) -> bool {
|
||||
match pat.node {
|
||||
ast::PatEnum(_, _) |
|
||||
ast::PatIdent(_, _, None) |
|
||||
|
@ -59,7 +58,7 @@ pub fn pat_is_variant_or_struct(dm: &resolve::DefMap, pat: &ast::Pat) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pat_is_const(dm: &resolve::DefMap, pat: &ast::Pat) -> bool {
|
||||
pub fn pat_is_const(dm: &DefMap, pat: &ast::Pat) -> bool {
|
||||
match pat.node {
|
||||
ast::PatIdent(_, _, None) | ast::PatEnum(..) => {
|
||||
match dm.borrow().get(&pat.id) {
|
||||
|
@ -71,7 +70,7 @@ pub fn pat_is_const(dm: &resolve::DefMap, pat: &ast::Pat) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pat_is_binding(dm: &resolve::DefMap, pat: &ast::Pat) -> bool {
|
||||
pub fn pat_is_binding(dm: &DefMap, pat: &ast::Pat) -> bool {
|
||||
match pat.node {
|
||||
ast::PatIdent(..) => {
|
||||
!pat_is_variant_or_struct(dm, pat) &&
|
||||
|
@ -81,7 +80,7 @@ pub fn pat_is_binding(dm: &resolve::DefMap, pat: &ast::Pat) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pat_is_binding_or_wild(dm: &resolve::DefMap, pat: &ast::Pat) -> bool {
|
||||
pub fn pat_is_binding_or_wild(dm: &DefMap, pat: &ast::Pat) -> bool {
|
||||
match pat.node {
|
||||
ast::PatIdent(..) => pat_is_binding(dm, pat),
|
||||
ast::PatWild(_) => true,
|
||||
|
@ -91,7 +90,7 @@ pub fn pat_is_binding_or_wild(dm: &resolve::DefMap, pat: &ast::Pat) -> bool {
|
|||
|
||||
/// Call `it` on every "binding" in a pattern, e.g., on `a` in
|
||||
/// `match foo() { Some(a) => (), None => () }`
|
||||
pub fn pat_bindings<I>(dm: &resolve::DefMap, pat: &ast::Pat, mut it: I) where
|
||||
pub fn pat_bindings<I>(dm: &DefMap, pat: &ast::Pat, mut it: I) where
|
||||
I: FnMut(ast::BindingMode, ast::NodeId, Span, &ast::SpannedIdent),
|
||||
{
|
||||
walk_pat(pat, |p| {
|
||||
|
@ -107,7 +106,7 @@ pub fn pat_bindings<I>(dm: &resolve::DefMap, pat: &ast::Pat, mut it: I) where
|
|||
|
||||
/// Checks if the pattern contains any patterns that bind something to
|
||||
/// an ident, e.g. `foo`, or `Foo(foo)` or `foo @ Bar(..)`.
|
||||
pub fn pat_contains_bindings(dm: &resolve::DefMap, pat: &ast::Pat) -> bool {
|
||||
pub fn pat_contains_bindings(dm: &DefMap, pat: &ast::Pat) -> bool {
|
||||
let mut contains_bindings = false;
|
||||
walk_pat(pat, |p| {
|
||||
if pat_is_binding(dm, p) {
|
||||
|
|
|
@ -11,17 +11,20 @@
|
|||
//! A pass that checks to make sure private fields and methods aren't used
|
||||
//! outside their scopes. This pass will also generate a set of exported items
|
||||
//! which are available for use externally when compiled as a library.
|
||||
pub use self::PrivateDep::*;
|
||||
pub use self::ImportUse::*;
|
||||
pub use self::LastPrivate::*;
|
||||
use self::PrivacyResult::*;
|
||||
use self::FieldName::*;
|
||||
|
||||
use std::mem::replace;
|
||||
|
||||
use metadata::csearch;
|
||||
use middle::{def, resolve};
|
||||
use middle::def;
|
||||
use middle::ty::{mod, Ty};
|
||||
use middle::ty::{MethodCall, MethodMap, MethodOrigin, MethodParam, MethodTypeParam};
|
||||
use middle::ty::{MethodStatic, MethodStaticUnboxedClosure, MethodObject, MethodTraitObject};
|
||||
use util::nodemap::{NodeMap, NodeSet};
|
||||
use util::nodemap::{DefIdSet, NodeMap, NodeSet};
|
||||
|
||||
use syntax::{ast, ast_map};
|
||||
use syntax::ast_util::{is_local, local_def, PostExpansionMethod};
|
||||
|
@ -29,16 +32,59 @@ use syntax::codemap::Span;
|
|||
use syntax::parse::token;
|
||||
use syntax::visit::{mod, Visitor};
|
||||
|
||||
type Context<'a, 'tcx> = (&'a MethodMap<'tcx>, &'a resolve::ExportMap2);
|
||||
type Context<'a, 'tcx> = (&'a MethodMap<'tcx>, &'a def::ExportMap);
|
||||
|
||||
/// A set of AST nodes exported by the crate.
|
||||
pub type ExportedItems = NodeSet;
|
||||
|
||||
/// A set containing all exported definitions from external crates.
|
||||
/// The set does not contain any entries from local crates.
|
||||
pub type ExternalExports = DefIdSet;
|
||||
|
||||
/// A set of AST nodes that are fully public in the crate. This map is used for
|
||||
/// documentation purposes (reexporting a private struct inlines the doc,
|
||||
/// reexporting a public struct doesn't inline the doc).
|
||||
pub type PublicItems = NodeSet;
|
||||
|
||||
// FIXME: dox
|
||||
pub type LastPrivateMap = NodeMap<LastPrivate>;
|
||||
|
||||
#[deriving(Copy, Show)]
|
||||
pub enum LastPrivate {
|
||||
LastMod(PrivateDep),
|
||||
// `use` directives (imports) can refer to two separate definitions in the
|
||||
// type and value namespaces. We record here the last private node for each
|
||||
// and whether the import is in fact used for each.
|
||||
// If the Option<PrivateDep> fields are None, it means there is no definition
|
||||
// in that namespace.
|
||||
LastImport{value_priv: Option<PrivateDep>,
|
||||
value_used: ImportUse,
|
||||
type_priv: Option<PrivateDep>,
|
||||
type_used: ImportUse},
|
||||
}
|
||||
|
||||
#[deriving(Copy, Show)]
|
||||
pub enum PrivateDep {
|
||||
AllPublic,
|
||||
DependsOn(ast::DefId),
|
||||
}
|
||||
|
||||
// How an import is used.
|
||||
#[deriving(Copy, PartialEq, Show)]
|
||||
pub enum ImportUse {
|
||||
Unused, // The import is not used.
|
||||
Used, // The import is used.
|
||||
}
|
||||
|
||||
impl LastPrivate {
|
||||
pub fn or(self, other: LastPrivate) -> LastPrivate {
|
||||
match (self, other) {
|
||||
(me, LastMod(AllPublic)) => me,
|
||||
(_, other) => other,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Result of a checking operation - None => no errors were found. Some => an
|
||||
/// error and contains the span and message for reporting that error and
|
||||
/// optionally the same for a note about the error.
|
||||
|
@ -136,7 +182,7 @@ impl<'v> Visitor<'v> for ParentVisitor {
|
|||
|
||||
struct EmbargoVisitor<'a, 'tcx: 'a> {
|
||||
tcx: &'a ty::ctxt<'tcx>,
|
||||
exp_map2: &'a resolve::ExportMap2,
|
||||
export_map: &'a def::ExportMap,
|
||||
|
||||
// This flag is an indicator of whether the previous item in the
|
||||
// hierarchical chain was exported or not. This is the indicator of whether
|
||||
|
@ -342,8 +388,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
|
|||
// This code is here instead of in visit_item so that the
|
||||
// crate module gets processed as well.
|
||||
if self.prev_exported {
|
||||
assert!(self.exp_map2.contains_key(&id), "wut {}", id);
|
||||
for export in self.exp_map2[id].iter() {
|
||||
assert!(self.export_map.contains_key(&id), "wut {}", id);
|
||||
for export in self.export_map[id].iter() {
|
||||
if is_local(export.def_id) {
|
||||
self.reexports.insert(export.def_id.node);
|
||||
}
|
||||
|
@ -362,8 +408,8 @@ struct PrivacyVisitor<'a, 'tcx: 'a> {
|
|||
curitem: ast::NodeId,
|
||||
in_foreign: bool,
|
||||
parents: NodeMap<ast::NodeId>,
|
||||
external_exports: resolve::ExternalExports,
|
||||
last_private_map: resolve::LastPrivateMap,
|
||||
external_exports: ExternalExports,
|
||||
last_private_map: LastPrivateMap,
|
||||
}
|
||||
|
||||
enum PrivacyResult {
|
||||
|
@ -719,25 +765,25 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
|||
};
|
||||
|
||||
match self.last_private_map[path_id] {
|
||||
resolve::LastMod(resolve::AllPublic) => {},
|
||||
resolve::LastMod(resolve::DependsOn(def)) => {
|
||||
LastMod(AllPublic) => {},
|
||||
LastMod(DependsOn(def)) => {
|
||||
self.report_error(ck_public(def));
|
||||
},
|
||||
resolve::LastImport{value_priv,
|
||||
value_used: check_value,
|
||||
type_priv,
|
||||
type_used: check_type} => {
|
||||
LastImport { value_priv,
|
||||
value_used: check_value,
|
||||
type_priv,
|
||||
type_used: check_type } => {
|
||||
// This dance with found_error is because we don't want to report
|
||||
// a privacy error twice for the same directive.
|
||||
let found_error = match (type_priv, check_type) {
|
||||
(Some(resolve::DependsOn(def)), resolve::Used) => {
|
||||
(Some(DependsOn(def)), Used) => {
|
||||
!self.report_error(ck_public(def))
|
||||
},
|
||||
_ => false,
|
||||
};
|
||||
if !found_error {
|
||||
match (value_priv, check_value) {
|
||||
(Some(resolve::DependsOn(def)), resolve::Used) => {
|
||||
(Some(DependsOn(def)), Used) => {
|
||||
self.report_error(ck_public(def));
|
||||
},
|
||||
_ => {},
|
||||
|
@ -749,24 +795,24 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
|||
// be illegal. We only report one error, even if it is
|
||||
// illegal to import from both namespaces.
|
||||
match (value_priv, check_value, type_priv, check_type) {
|
||||
(Some(p), resolve::Unused, None, _) |
|
||||
(None, _, Some(p), resolve::Unused) => {
|
||||
(Some(p), Unused, None, _) |
|
||||
(None, _, Some(p), Unused) => {
|
||||
let p = match p {
|
||||
resolve::AllPublic => None,
|
||||
resolve::DependsOn(def) => ck_public(def),
|
||||
AllPublic => None,
|
||||
DependsOn(def) => ck_public(def),
|
||||
};
|
||||
if p.is_some() {
|
||||
self.report_error(p);
|
||||
}
|
||||
},
|
||||
(Some(v), resolve::Unused, Some(t), resolve::Unused) => {
|
||||
(Some(v), Unused, Some(t), Unused) => {
|
||||
let v = match v {
|
||||
resolve::AllPublic => None,
|
||||
resolve::DependsOn(def) => ck_public(def),
|
||||
AllPublic => None,
|
||||
DependsOn(def) => ck_public(def),
|
||||
};
|
||||
let t = match t {
|
||||
resolve::AllPublic => None,
|
||||
resolve::DependsOn(def) => ck_public(def),
|
||||
AllPublic => None,
|
||||
DependsOn(def) => ck_public(def),
|
||||
};
|
||||
if let (Some(_), Some(t)) = (v, t) {
|
||||
self.report_error(Some(t));
|
||||
|
@ -1520,9 +1566,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn check_crate(tcx: &ty::ctxt,
|
||||
exp_map2: &resolve::ExportMap2,
|
||||
external_exports: resolve::ExternalExports,
|
||||
last_private_map: resolve::LastPrivateMap)
|
||||
export_map: &def::ExportMap,
|
||||
external_exports: ExternalExports,
|
||||
last_private_map: LastPrivateMap)
|
||||
-> (ExportedItems, PublicItems) {
|
||||
let krate = tcx.map.krate();
|
||||
|
||||
|
@ -1561,7 +1607,7 @@ pub fn check_crate(tcx: &ty::ctxt,
|
|||
exported_items: NodeSet::new(),
|
||||
public_items: NodeSet::new(),
|
||||
reexports: NodeSet::new(),
|
||||
exp_map2: exp_map2,
|
||||
export_map: export_map,
|
||||
prev_exported: true,
|
||||
prev_public: true,
|
||||
};
|
||||
|
|
|
@ -19,9 +19,8 @@ pub use self::DefRegion::*;
|
|||
use self::ScopeChain::*;
|
||||
|
||||
use session::Session;
|
||||
use middle::def;
|
||||
use middle::def::{mod, DefMap};
|
||||
use middle::region;
|
||||
use middle::resolve::DefMap;
|
||||
use middle::subst;
|
||||
use middle::ty;
|
||||
use std::fmt;
|
||||
|
|
|
@ -46,13 +46,12 @@ use lint;
|
|||
use metadata::csearch;
|
||||
use middle;
|
||||
use middle::const_eval;
|
||||
use middle::def;
|
||||
use middle::def::{mod, DefMap, ExportMap};
|
||||
use middle::dependency_format;
|
||||
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
|
||||
use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem};
|
||||
use middle::mem_categorization as mc;
|
||||
use middle::region;
|
||||
use middle::resolve;
|
||||
use middle::resolve_lifetime;
|
||||
use middle::infer;
|
||||
use middle::stability;
|
||||
|
@ -99,7 +98,7 @@ pub const INITIAL_DISCRIMINANT_VALUE: Disr = 0;
|
|||
/// The complete set of all analyses described in this module. This is
|
||||
/// produced by the driver and fed to trans and later passes.
|
||||
pub struct CrateAnalysis<'tcx> {
|
||||
pub exp_map2: middle::resolve::ExportMap2,
|
||||
pub export_map: ExportMap,
|
||||
pub exported_items: middle::privacy::ExportedItems,
|
||||
pub public_items: middle::privacy::PublicItems,
|
||||
pub ty_cx: ty::ctxt<'tcx>,
|
||||
|
@ -615,7 +614,7 @@ pub struct ctxt<'tcx> {
|
|||
// queried from a HashSet.
|
||||
interner: RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
|
||||
pub sess: Session,
|
||||
pub def_map: resolve::DefMap,
|
||||
pub def_map: DefMap,
|
||||
|
||||
pub named_region_map: resolve_lifetime::NamedRegionMap,
|
||||
|
||||
|
@ -1967,7 +1966,7 @@ impl UnboxedClosureKind {
|
|||
|
||||
pub fn mk_ctxt<'tcx>(s: Session,
|
||||
type_arena: &'tcx TypedArena<TyS<'tcx>>,
|
||||
dm: resolve::DefMap,
|
||||
dm: DefMap,
|
||||
named_region_map: resolve_lifetime::NamedRegionMap,
|
||||
map: ast_map::Map<'tcx>,
|
||||
freevars: RefCell<FreevarMap>,
|
||||
|
@ -6263,6 +6262,9 @@ pub type FreevarMap = NodeMap<Vec<Freevar>>;
|
|||
|
||||
pub type CaptureModeMap = NodeMap<ast::CaptureClause>;
|
||||
|
||||
// Trait method resolution
|
||||
pub type TraitMap = NodeMap<Vec<DefId>>;
|
||||
|
||||
pub fn with_freevars<T, F>(tcx: &ty::ctxt, fid: ast::NodeId, f: F) -> T where
|
||||
F: FnOnce(&[Freevar]) -> T,
|
||||
{
|
||||
|
|
|
@ -20,6 +20,7 @@ use rustc::plugin::registry::Registry;
|
|||
use rustc::plugin;
|
||||
use rustc::util::common::time;
|
||||
use rustc_borrowck as borrowck;
|
||||
use rustc_resolve as resolve;
|
||||
use rustc_trans::back::link;
|
||||
use rustc_trans::back::write;
|
||||
use rustc_trans::save;
|
||||
|
@ -341,17 +342,17 @@ 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 middle::resolve::CrateMap {
|
||||
let resolve::CrateMap {
|
||||
def_map,
|
||||
freevars,
|
||||
capture_mode_map,
|
||||
exp_map2,
|
||||
export_map,
|
||||
trait_map,
|
||||
external_exports,
|
||||
last_private_map
|
||||
} =
|
||||
time(time_passes, "resolution", (), |_|
|
||||
middle::resolve::resolve_crate(&sess, &lang_items, krate));
|
||||
time(time_passes, "resolution", (),
|
||||
|_| resolve::resolve_crate(&sess, &lang_items, krate));
|
||||
|
||||
// Discard MTWT tables that aren't required past resolution.
|
||||
syntax::ext::mtwt::clear_tables();
|
||||
|
@ -406,7 +407,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
|
|||
let maps = (external_exports, last_private_map);
|
||||
let (exported_items, public_items) =
|
||||
time(time_passes, "privacy checking", maps, |(a, b)|
|
||||
middle::privacy::check_crate(&ty_cx, &exp_map2, a, b));
|
||||
middle::privacy::check_crate(&ty_cx, &export_map, a, b));
|
||||
|
||||
time(time_passes, "intrinsic checking", (), |_|
|
||||
middle::intrinsicck::check_crate(&ty_cx));
|
||||
|
@ -447,7 +448,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
|
|||
lint::check_crate(&ty_cx, &exported_items));
|
||||
|
||||
ty::CrateAnalysis {
|
||||
exp_map2: exp_map2,
|
||||
export_map: export_map,
|
||||
ty_cx: ty_cx,
|
||||
exported_items: exported_items,
|
||||
public_items: public_items,
|
||||
|
|
|
@ -35,6 +35,7 @@ extern crate libc;
|
|||
extern crate rustc;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_borrowck;
|
||||
extern crate rustc_resolve;
|
||||
extern crate rustc_trans;
|
||||
extern crate rustc_typeck;
|
||||
#[phase(plugin, link)] extern crate log;
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
use diagnostic;
|
||||
use diagnostic::Emitter;
|
||||
use driver;
|
||||
use rustc_resolve as resolve;
|
||||
use rustc_typeck::middle::lang_items;
|
||||
use rustc_typeck::middle::region::{mod, CodeExtent};
|
||||
use rustc_typeck::middle::resolve;
|
||||
use rustc_typeck::middle::resolve_lifetime;
|
||||
use rustc_typeck::middle::stability;
|
||||
use rustc_typeck::middle::subst;
|
||||
|
|
161
src/librustc_resolve/check_unused.rs
Normal file
161
src/librustc_resolve/check_unused.rs
Normal file
|
@ -0,0 +1,161 @@
|
|||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
//
|
||||
// Unused import checking
|
||||
//
|
||||
// Although this is mostly a lint pass, it lives in here because it depends on
|
||||
// resolve data structures and because it finalises the privacy information for
|
||||
// `use` directives.
|
||||
//
|
||||
|
||||
use Resolver;
|
||||
use Namespace::{TypeNS, ValueNS};
|
||||
|
||||
use rustc::lint;
|
||||
use rustc::middle::privacy::{DependsOn, LastImport, Used, Unused};
|
||||
use syntax::ast;
|
||||
use syntax::ast::{ViewItem, ViewItemExternCrate, ViewItemUse};
|
||||
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>
|
||||
}
|
||||
|
||||
// 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> {
|
||||
&*self.resolver
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> DerefMut<Resolver<'b>> for UnusedImportCheckVisitor<'a, 'b> {
|
||||
fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> {
|
||||
&mut *self.resolver
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> {
|
||||
// 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
|
||||
// information. That means in privacy.rs, we will only check imports and namespaces
|
||||
// which are used. In particular, this means that if an import could name either a
|
||||
// public or private item, we will check the correct thing, dependent on how the import
|
||||
// is used.
|
||||
fn finalize_import(&mut self, id: ast::NodeId, span: Span) {
|
||||
debug!("finalizing import uses for {}",
|
||||
self.session.codemap().span_to_snippet(span));
|
||||
|
||||
if !self.used_imports.contains(&(id, TypeNS)) &&
|
||||
!self.used_imports.contains(&(id, ValueNS)) {
|
||||
self.session.add_lint(lint::builtin::UNUSED_IMPORTS,
|
||||
id,
|
||||
span,
|
||||
"unused import".to_string());
|
||||
}
|
||||
|
||||
let (v_priv, t_priv) = match self.last_private.get(&id) {
|
||||
Some(&LastImport {
|
||||
value_priv: v,
|
||||
value_used: _,
|
||||
type_priv: t,
|
||||
type_used: _
|
||||
}) => (v, t),
|
||||
Some(_) => {
|
||||
panic!("we should only have LastImport for `use` directives")
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let mut v_used = if self.used_imports.contains(&(id, ValueNS)) {
|
||||
Used
|
||||
} else {
|
||||
Unused
|
||||
};
|
||||
let t_used = if self.used_imports.contains(&(id, TypeNS)) {
|
||||
Used
|
||||
} else {
|
||||
Unused
|
||||
};
|
||||
|
||||
match (v_priv, t_priv) {
|
||||
// Since some items may be both in the value _and_ type namespaces (e.g., structs)
|
||||
// we might have two LastPrivates pointing at the same thing. There is no point
|
||||
// checking both, so lets not check the value one.
|
||||
(Some(DependsOn(def_v)), Some(DependsOn(def_t))) if def_v == def_t => v_used = Unused,
|
||||
_ => {},
|
||||
}
|
||||
|
||||
self.last_private.insert(id, LastImport{value_priv: v_priv,
|
||||
value_used: v_used,
|
||||
type_priv: t_priv,
|
||||
type_used: t_used});
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'v> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b> {
|
||||
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
|
||||
// because this means that they were generated in some fashion by the
|
||||
// compiler and we don't need to consider them.
|
||||
if vi.vis == ast::Public || vi.span == DUMMY_SP {
|
||||
visit::walk_view_item(self, vi);
|
||||
return;
|
||||
}
|
||||
|
||||
match vi.node {
|
||||
ViewItemExternCrate(_, _, id) => {
|
||||
if let Some(crate_num) = self.session.cstore.find_extern_mod_stmt_cnum(id) {
|
||||
if !self.used_crates.contains(&crate_num) {
|
||||
self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATES,
|
||||
id,
|
||||
vi.span,
|
||||
"unused extern crate".to_string());
|
||||
}
|
||||
}
|
||||
},
|
||||
ViewItemUse(ref p) => {
|
||||
match p.node {
|
||||
ViewPathSimple(_, _, id) => {
|
||||
self.finalize_import(id, p.span)
|
||||
}
|
||||
|
||||
ViewPathList(_, ref list, _) => {
|
||||
for i in list.iter() {
|
||||
self.finalize_import(i.node.id(), i.span);
|
||||
}
|
||||
}
|
||||
ViewPathGlob(_, id) => {
|
||||
if !self.used_imports.contains(&(id, TypeNS)) &&
|
||||
!self.used_imports.contains(&(id, ValueNS)) {
|
||||
self.session
|
||||
.add_lint(lint::builtin::UNUSED_IMPORTS,
|
||||
id,
|
||||
p.span,
|
||||
"unused import".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visit::walk_view_item(self, vi);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
|
||||
let mut visitor = UnusedImportCheckVisitor { resolver: resolver };
|
||||
visit::walk_crate(&mut visitor, krate);
|
||||
}
|
|
@ -8,12 +8,22 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
#![crate_name = "rustc_resolve"]
|
||||
#![experimental]
|
||||
#![crate_type = "dylib"]
|
||||
#![crate_type = "rlib"]
|
||||
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
||||
|
||||
#![feature(globs, phase, slicing_syntax)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
|
||||
#[phase(plugin, link)] extern crate log;
|
||||
#[phase(plugin, link)] extern crate syntax;
|
||||
|
||||
extern crate rustc;
|
||||
|
||||
pub use self::PrivateDep::*;
|
||||
pub use self::ImportUse::*;
|
||||
pub use self::TraitItemKind::*;
|
||||
pub use self::LastPrivate::*;
|
||||
use self::PatternBindingMode::*;
|
||||
use self::Namespace::*;
|
||||
use self::NamespaceError::*;
|
||||
|
@ -36,26 +46,26 @@ use self::ModuleKind::*;
|
|||
use self::TraitReferenceType::*;
|
||||
use self::FallbackChecks::*;
|
||||
|
||||
use session::Session;
|
||||
use lint;
|
||||
use metadata::csearch;
|
||||
use metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
|
||||
use middle::def::*;
|
||||
use middle::lang_items::LanguageItems;
|
||||
use middle::pat_util::pat_bindings;
|
||||
use middle::subst::{ParamSpace, FnSpace, TypeSpace};
|
||||
use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory};
|
||||
use middle::ty::{CaptureModeMap, Freevar, FreevarMap};
|
||||
use util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap};
|
||||
use rustc::session::Session;
|
||||
use rustc::lint;
|
||||
use rustc::metadata::csearch;
|
||||
use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
|
||||
use rustc::middle::def::*;
|
||||
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::util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap};
|
||||
|
||||
use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
|
||||
use syntax::ast::{DeclItem, DefId, Expr, ExprAgain, ExprBreak, ExprField};
|
||||
use syntax::ast::{ExprClosure, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall};
|
||||
use syntax::ast::{ExprPath, ExprStruct, FnDecl};
|
||||
use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic, Generics};
|
||||
use syntax::ast::{Ident, ImplItem, Item, ItemEnum, ItemFn, ItemForeignMod};
|
||||
use syntax::ast::{ItemImpl, ItemMac, ItemMod, ItemStatic, ItemStruct};
|
||||
use syntax::ast::{ItemTrait, ItemTy, LOCAL_CRATE, Local, ItemConst};
|
||||
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::{MethodImplItem, Mod, Name, NamedField, NodeId};
|
||||
use syntax::ast::{Pat, PatEnum, PatIdent, PatLit};
|
||||
use syntax::ast::{PatRange, PatStruct, Path, PathListIdent, PathListMod};
|
||||
|
@ -86,72 +96,17 @@ use std::mem::replace;
|
|||
use std::rc::{Rc, Weak};
|
||||
use std::uint;
|
||||
|
||||
// Definition mapping
|
||||
pub type DefMap = RefCell<NodeMap<Def>>;
|
||||
mod check_unused;
|
||||
mod record_exports;
|
||||
|
||||
#[deriving(Copy)]
|
||||
struct binding_info {
|
||||
struct BindingInfo {
|
||||
span: Span,
|
||||
binding_mode: BindingMode,
|
||||
}
|
||||
|
||||
// Map from the name in a pattern to its binding mode.
|
||||
type BindingMap = HashMap<Name,binding_info>;
|
||||
|
||||
// Trait method resolution
|
||||
pub type TraitMap = NodeMap<Vec<DefId> >;
|
||||
|
||||
// This is the replacement export map. It maps a module to all of the exports
|
||||
// within.
|
||||
pub type ExportMap2 = NodeMap<Vec<Export2>>;
|
||||
|
||||
pub struct Export2 {
|
||||
pub name: String, // The name of the target.
|
||||
pub def_id: DefId, // The definition of the target.
|
||||
}
|
||||
|
||||
// This set contains all exported definitions from external crates. The set does
|
||||
// not contain any entries from local crates.
|
||||
pub type ExternalExports = DefIdSet;
|
||||
|
||||
// FIXME: dox
|
||||
pub type LastPrivateMap = NodeMap<LastPrivate>;
|
||||
|
||||
#[deriving(Copy, Show)]
|
||||
pub enum LastPrivate {
|
||||
LastMod(PrivateDep),
|
||||
// `use` directives (imports) can refer to two separate definitions in the
|
||||
// type and value namespaces. We record here the last private node for each
|
||||
// and whether the import is in fact used for each.
|
||||
// If the Option<PrivateDep> fields are None, it means there is no definition
|
||||
// in that namespace.
|
||||
LastImport{value_priv: Option<PrivateDep>,
|
||||
value_used: ImportUse,
|
||||
type_priv: Option<PrivateDep>,
|
||||
type_used: ImportUse},
|
||||
}
|
||||
|
||||
#[deriving(Copy, Show)]
|
||||
pub enum PrivateDep {
|
||||
AllPublic,
|
||||
DependsOn(DefId),
|
||||
}
|
||||
|
||||
// How an import is used.
|
||||
#[deriving(Copy, PartialEq, Show)]
|
||||
pub enum ImportUse {
|
||||
Unused, // The import is not used.
|
||||
Used, // The import is used.
|
||||
}
|
||||
|
||||
impl LastPrivate {
|
||||
fn or(self, other: LastPrivate) -> LastPrivate {
|
||||
match (self, other) {
|
||||
(me, LastMod(AllPublic)) => me,
|
||||
(_, other) => other,
|
||||
}
|
||||
}
|
||||
}
|
||||
type BindingMap = HashMap<Name, BindingInfo>;
|
||||
|
||||
#[deriving(Copy, PartialEq)]
|
||||
enum PatternBindingMode {
|
||||
|
@ -340,25 +295,6 @@ enum ModulePrefixResult {
|
|||
PrefixFound(Rc<Module>, uint)
|
||||
}
|
||||
|
||||
#[deriving(Clone, Copy, Eq, PartialEq)]
|
||||
pub enum TraitItemKind {
|
||||
NonstaticMethodTraitItemKind,
|
||||
StaticMethodTraitItemKind,
|
||||
TypeTraitItemKind,
|
||||
}
|
||||
|
||||
impl TraitItemKind {
|
||||
pub fn from_explicit_self_category(explicit_self_category:
|
||||
ExplicitSelfCategory)
|
||||
-> TraitItemKind {
|
||||
if explicit_self_category == StaticExplicitSelfCategory {
|
||||
StaticMethodTraitItemKind
|
||||
} else {
|
||||
NonstaticMethodTraitItemKind
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Copy, PartialEq)]
|
||||
enum NameSearchType {
|
||||
/// We're doing a name search in order to resolve a `use` directive.
|
||||
|
@ -948,7 +884,7 @@ struct Resolver<'a> {
|
|||
freevars: RefCell<FreevarMap>,
|
||||
freevars_seen: RefCell<NodeMap<NodeSet>>,
|
||||
capture_mode_map: CaptureModeMap,
|
||||
export_map2: ExportMap2,
|
||||
export_map: ExportMap,
|
||||
trait_map: TraitMap,
|
||||
external_exports: ExternalExports,
|
||||
last_private: LastPrivateMap,
|
||||
|
@ -1002,17 +938,6 @@ impl<'a, 'b, 'v> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b> {
|
|||
|
||||
}
|
||||
|
||||
struct UnusedImportCheckVisitor<'a, 'b:'a> {
|
||||
resolver: &'a mut Resolver<'b>
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'v> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b> {
|
||||
fn visit_view_item(&mut self, vi: &ViewItem) {
|
||||
self.resolver.check_for_item_unused_imports(vi);
|
||||
visit::walk_view_item(self, vi);
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(PartialEq)]
|
||||
enum FallbackChecks {
|
||||
Everything,
|
||||
|
@ -1063,7 +988,7 @@ impl<'a> Resolver<'a> {
|
|||
freevars: RefCell::new(NodeMap::new()),
|
||||
freevars_seen: RefCell::new(NodeMap::new()),
|
||||
capture_mode_map: NodeMap::new(),
|
||||
export_map2: NodeMap::new(),
|
||||
export_map: NodeMap::new(),
|
||||
trait_map: NodeMap::new(),
|
||||
used_imports: HashSet::new(),
|
||||
used_crates: HashSet::new(),
|
||||
|
@ -1073,22 +998,6 @@ impl<'a> Resolver<'a> {
|
|||
emit_errors: true,
|
||||
}
|
||||
}
|
||||
/// The main name resolution procedure.
|
||||
fn resolve(&mut self, krate: &ast::Crate) {
|
||||
self.build_reduced_graph(krate);
|
||||
self.session.abort_if_errors();
|
||||
|
||||
self.resolve_imports();
|
||||
self.session.abort_if_errors();
|
||||
|
||||
self.record_exports();
|
||||
self.session.abort_if_errors();
|
||||
|
||||
self.resolve_crate(krate);
|
||||
self.session.abort_if_errors();
|
||||
|
||||
self.check_for_unused_imports(krate);
|
||||
}
|
||||
|
||||
//
|
||||
// Reduced graph building
|
||||
|
@ -3800,125 +3709,6 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
// Export recording
|
||||
//
|
||||
// This pass simply determines what all "export" keywords refer to and
|
||||
// writes the results into the export map.
|
||||
//
|
||||
// FIXME #4953 This pass will be removed once exports change to per-item.
|
||||
// Then this operation can simply be performed as part of item (or import)
|
||||
// processing.
|
||||
|
||||
fn record_exports(&mut self) {
|
||||
let root_module = self.graph_root.get_module();
|
||||
self.record_exports_for_module_subtree(root_module);
|
||||
}
|
||||
|
||||
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
|
||||
// exports for nonlocal crates.
|
||||
|
||||
match module_.def_id.get() {
|
||||
Some(def_id) if def_id.krate == LOCAL_CRATE => {
|
||||
// OK. Continue.
|
||||
debug!("(recording exports for module subtree) recording \
|
||||
exports for local module `{}`",
|
||||
self.module_to_string(&*module_));
|
||||
}
|
||||
None => {
|
||||
// Record exports for the root module.
|
||||
debug!("(recording exports for module subtree) recording \
|
||||
exports for root module `{}`",
|
||||
self.module_to_string(&*module_));
|
||||
}
|
||||
Some(_) => {
|
||||
// Bail out.
|
||||
debug!("(recording exports for module subtree) not recording \
|
||||
exports for `{}`",
|
||||
self.module_to_string(&*module_));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.record_exports_for_module(&*module_);
|
||||
self.populate_module_if_necessary(&module_);
|
||||
|
||||
for (_, child_name_bindings) in module_.children.borrow().iter() {
|
||||
match child_name_bindings.get_module_if_available() {
|
||||
None => {
|
||||
// Nothing to do.
|
||||
}
|
||||
Some(child_module) => {
|
||||
self.record_exports_for_module_subtree(child_module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (_, child_module) in module_.anonymous_children.borrow().iter() {
|
||||
self.record_exports_for_module_subtree(child_module.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn record_exports_for_module(&mut self, module_: &Module) {
|
||||
let mut exports2 = Vec::new();
|
||||
|
||||
self.add_exports_for_module(&mut exports2, module_);
|
||||
match module_.def_id.get() {
|
||||
Some(def_id) => {
|
||||
self.export_map2.insert(def_id.node, exports2);
|
||||
debug!("(computing exports) writing exports for {} (some)",
|
||||
def_id.node);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_exports_of_namebindings(&mut self,
|
||||
exports2: &mut Vec<Export2> ,
|
||||
name: Name,
|
||||
namebindings: &NameBindings,
|
||||
ns: Namespace) {
|
||||
match namebindings.def_for_namespace(ns) {
|
||||
Some(d) => {
|
||||
let name = token::get_name(name);
|
||||
debug!("(computing exports) YES: export '{}' => {}",
|
||||
name, d.def_id());
|
||||
exports2.push(Export2 {
|
||||
name: name.get().to_string(),
|
||||
def_id: d.def_id()
|
||||
});
|
||||
}
|
||||
d_opt => {
|
||||
debug!("(computing exports) NO: {}", d_opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_exports_for_module(&mut self,
|
||||
exports2: &mut Vec<Export2> ,
|
||||
module_: &Module) {
|
||||
for (name, importresolution) in module_.import_resolutions.borrow().iter() {
|
||||
if !importresolution.is_public {
|
||||
continue
|
||||
}
|
||||
let xs = [TypeNS, ValueNS];
|
||||
for &ns in xs.iter() {
|
||||
match importresolution.target_for_namespace(ns) {
|
||||
Some(target) => {
|
||||
debug!("(computing exports) maybe export '{}'",
|
||||
token::get_name(*name));
|
||||
self.add_exports_of_namebindings(exports2,
|
||||
*name,
|
||||
&*target.bindings,
|
||||
ns)
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AST resolution
|
||||
//
|
||||
// We maintain a list of value ribs and type ribs.
|
||||
|
@ -4809,9 +4599,10 @@ impl<'a> Resolver<'a> {
|
|||
let mut result = HashMap::new();
|
||||
pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path1| {
|
||||
let name = mtwt::resolve(path1.node);
|
||||
result.insert(name,
|
||||
binding_info {span: sp,
|
||||
binding_mode: binding_mode});
|
||||
result.insert(name, BindingInfo {
|
||||
span: sp,
|
||||
binding_mode: binding_mode
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
@ -6135,119 +5926,6 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Unused import checking
|
||||
//
|
||||
// Although this is mostly a lint pass, it lives in here because it depends on
|
||||
// resolve data structures and because it finalises the privacy information for
|
||||
// `use` directives.
|
||||
//
|
||||
|
||||
fn check_for_unused_imports(&mut self, krate: &ast::Crate) {
|
||||
let mut visitor = UnusedImportCheckVisitor{ resolver: self };
|
||||
visit::walk_crate(&mut visitor, krate);
|
||||
}
|
||||
|
||||
fn check_for_item_unused_imports(&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
|
||||
// because this means that they were generated in some fashion by the
|
||||
// compiler and we don't need to consider them.
|
||||
if vi.vis == Public { return }
|
||||
if vi.span == DUMMY_SP { return }
|
||||
|
||||
match vi.node {
|
||||
ViewItemExternCrate(_, _, id) => {
|
||||
if let Some(crate_num) = self.session.cstore.find_extern_mod_stmt_cnum(id) {
|
||||
if !self.used_crates.contains(&crate_num) {
|
||||
self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATES,
|
||||
id,
|
||||
vi.span,
|
||||
"unused extern crate".to_string());
|
||||
}
|
||||
}
|
||||
},
|
||||
ViewItemUse(ref p) => {
|
||||
match p.node {
|
||||
ViewPathSimple(_, _, id) => self.finalize_import(id, p.span),
|
||||
|
||||
ViewPathList(_, ref list, _) => {
|
||||
for i in list.iter() {
|
||||
self.finalize_import(i.node.id(), i.span);
|
||||
}
|
||||
},
|
||||
ViewPathGlob(_, id) => {
|
||||
if !self.used_imports.contains(&(id, TypeNS)) &&
|
||||
!self.used_imports.contains(&(id, ValueNS)) {
|
||||
self.session
|
||||
.add_lint(lint::builtin::UNUSED_IMPORTS,
|
||||
id,
|
||||
p.span,
|
||||
"unused import".to_string());
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
// information. That means in privacy.rs, we will only check imports and namespaces
|
||||
// which are used. In particular, this means that if an import could name either a
|
||||
// public or private item, we will check the correct thing, dependent on how the import
|
||||
// is used.
|
||||
fn finalize_import(&mut self, id: NodeId, span: Span) {
|
||||
debug!("finalizing import uses for {}",
|
||||
self.session.codemap().span_to_snippet(span));
|
||||
|
||||
if !self.used_imports.contains(&(id, TypeNS)) &&
|
||||
!self.used_imports.contains(&(id, ValueNS)) {
|
||||
self.session.add_lint(lint::builtin::UNUSED_IMPORTS,
|
||||
id,
|
||||
span,
|
||||
"unused import".to_string());
|
||||
}
|
||||
|
||||
let (v_priv, t_priv) = match self.last_private.get(&id) {
|
||||
Some(&LastImport {
|
||||
value_priv: v,
|
||||
value_used: _,
|
||||
type_priv: t,
|
||||
type_used: _
|
||||
}) => (v, t),
|
||||
Some(_) => {
|
||||
panic!("we should only have LastImport for `use` directives")
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let mut v_used = if self.used_imports.contains(&(id, ValueNS)) {
|
||||
Used
|
||||
} else {
|
||||
Unused
|
||||
};
|
||||
let t_used = if self.used_imports.contains(&(id, TypeNS)) {
|
||||
Used
|
||||
} else {
|
||||
Unused
|
||||
};
|
||||
|
||||
match (v_priv, t_priv) {
|
||||
// Since some items may be both in the value _and_ type namespaces (e.g., structs)
|
||||
// we might have two LastPrivates pointing at the same thing. There is no point
|
||||
// checking both, so lets not check the value one.
|
||||
(Some(DependsOn(def_v)), Some(DependsOn(def_t))) if def_v == def_t => v_used = Unused,
|
||||
_ => {},
|
||||
}
|
||||
|
||||
self.last_private.insert(id, LastImport{value_priv: v_priv,
|
||||
value_used: v_used,
|
||||
type_priv: t_priv,
|
||||
type_used: t_used});
|
||||
}
|
||||
|
||||
//
|
||||
// Diagnostics
|
||||
//
|
||||
|
@ -6323,7 +6001,7 @@ pub struct CrateMap {
|
|||
pub def_map: DefMap,
|
||||
pub freevars: RefCell<FreevarMap>,
|
||||
pub capture_mode_map: RefCell<CaptureModeMap>,
|
||||
pub exp_map2: ExportMap2,
|
||||
pub export_map: ExportMap,
|
||||
pub trait_map: TraitMap,
|
||||
pub external_exports: ExternalExports,
|
||||
pub last_private_map: LastPrivateMap,
|
||||
|
@ -6335,12 +6013,26 @@ pub fn resolve_crate(session: &Session,
|
|||
krate: &Crate)
|
||||
-> CrateMap {
|
||||
let mut resolver = Resolver::new(session, krate.span);
|
||||
resolver.resolve(krate);
|
||||
|
||||
resolver.build_reduced_graph(krate);
|
||||
session.abort_if_errors();
|
||||
|
||||
resolver.resolve_imports();
|
||||
session.abort_if_errors();
|
||||
|
||||
record_exports::record(&mut resolver);
|
||||
session.abort_if_errors();
|
||||
|
||||
resolver.resolve_crate(krate);
|
||||
session.abort_if_errors();
|
||||
|
||||
check_unused::check_crate(&mut resolver, krate);
|
||||
|
||||
CrateMap {
|
||||
def_map: resolver.def_map,
|
||||
freevars: resolver.freevars,
|
||||
capture_mode_map: RefCell::new(resolver.capture_mode_map),
|
||||
exp_map2: resolver.export_map2,
|
||||
export_map: resolver.export_map,
|
||||
trait_map: resolver.trait_map,
|
||||
external_exports: resolver.external_exports,
|
||||
last_private_map: resolver.last_private,
|
157
src/librustc_resolve/record_exports.rs
Normal file
157
src/librustc_resolve/record_exports.rs
Normal file
|
@ -0,0 +1,157 @@
|
|||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
// Export recording
|
||||
//
|
||||
// This pass simply determines what all "export" keywords refer to and
|
||||
// writes the results into the export map.
|
||||
//
|
||||
// FIXME #4953 This pass will be removed once exports change to per-item.
|
||||
// Then this operation can simply be performed as part of item (or import)
|
||||
// processing.
|
||||
|
||||
use {Module, NameBindings, Resolver};
|
||||
use Namespace::{mod, TypeNS, ValueNS};
|
||||
|
||||
use rustc::middle::def::Export;
|
||||
use syntax::ast;
|
||||
use syntax::parse::token;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
struct ExportRecorder<'a, 'b:'a> {
|
||||
resolver: &'a mut Resolver<'b>
|
||||
}
|
||||
|
||||
// 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> {
|
||||
&*self.resolver
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> DerefMut<Resolver<'b>> for ExportRecorder<'a, 'b> {
|
||||
fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> {
|
||||
&mut *self.resolver
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> ExportRecorder<'a, 'b> {
|
||||
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
|
||||
// exports for nonlocal crates.
|
||||
|
||||
match module_.def_id.get() {
|
||||
Some(def_id) if def_id.krate == ast::LOCAL_CRATE => {
|
||||
// OK. Continue.
|
||||
debug!("(recording exports for module subtree) recording \
|
||||
exports for local module `{}`",
|
||||
self.module_to_string(&*module_));
|
||||
}
|
||||
None => {
|
||||
// Record exports for the root module.
|
||||
debug!("(recording exports for module subtree) recording \
|
||||
exports for root module `{}`",
|
||||
self.module_to_string(&*module_));
|
||||
}
|
||||
Some(_) => {
|
||||
// Bail out.
|
||||
debug!("(recording exports for module subtree) not recording \
|
||||
exports for `{}`",
|
||||
self.module_to_string(&*module_));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.record_exports_for_module(&*module_);
|
||||
self.populate_module_if_necessary(&module_);
|
||||
|
||||
for (_, child_name_bindings) in module_.children.borrow().iter() {
|
||||
match child_name_bindings.get_module_if_available() {
|
||||
None => {
|
||||
// Nothing to do.
|
||||
}
|
||||
Some(child_module) => {
|
||||
self.record_exports_for_module_subtree(child_module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (_, child_module) in module_.anonymous_children.borrow().iter() {
|
||||
self.record_exports_for_module_subtree(child_module.clone());
|
||||
}
|
||||
}
|
||||
|
||||
fn record_exports_for_module(&mut self, module_: &Module) {
|
||||
let mut exports = Vec::new();
|
||||
|
||||
self.add_exports_for_module(&mut exports, module_);
|
||||
match module_.def_id.get() {
|
||||
Some(def_id) => {
|
||||
self.export_map.insert(def_id.node, exports);
|
||||
debug!("(computing exports) writing exports for {} (some)",
|
||||
def_id.node);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_exports_of_namebindings(&mut self,
|
||||
exports: &mut Vec<Export>,
|
||||
name: ast::Name,
|
||||
namebindings: &NameBindings,
|
||||
ns: Namespace) {
|
||||
match namebindings.def_for_namespace(ns) {
|
||||
Some(d) => {
|
||||
debug!("(computing exports) YES: export '{}' => {}",
|
||||
name, d.def_id());
|
||||
exports.push(Export {
|
||||
name: name,
|
||||
def_id: d.def_id()
|
||||
});
|
||||
}
|
||||
d_opt => {
|
||||
debug!("(computing exports) NO: {}", d_opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_exports_for_module(&mut self,
|
||||
exports: &mut Vec<Export>,
|
||||
module_: &Module) {
|
||||
for (name, importresolution) in module_.import_resolutions.borrow().iter() {
|
||||
if !importresolution.is_public {
|
||||
continue
|
||||
}
|
||||
let xs = [TypeNS, ValueNS];
|
||||
for &ns in xs.iter() {
|
||||
match importresolution.target_for_namespace(ns) {
|
||||
Some(target) => {
|
||||
debug!("(computing exports) maybe export '{}'",
|
||||
token::get_name(*name));
|
||||
self.add_exports_of_namebindings(exports,
|
||||
*name,
|
||||
&*target.bindings,
|
||||
ns)
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn record(resolver: &mut Resolver) {
|
||||
let mut recorder = ExportRecorder { resolver: resolver };
|
||||
let root_module = recorder.graph_root.get_module();
|
||||
recorder.record_exports_for_module_subtree(root_module);
|
||||
}
|
|
@ -193,12 +193,11 @@ use llvm::{ValueRef, BasicBlockRef};
|
|||
use middle::check_match::StaticInliner;
|
||||
use middle::check_match;
|
||||
use middle::const_eval;
|
||||
use middle::def;
|
||||
use middle::def::{mod, DefMap};
|
||||
use middle::expr_use_visitor as euv;
|
||||
use middle::lang_items::StrEqFnLangItem;
|
||||
use middle::mem_categorization as mc;
|
||||
use middle::pat_util::*;
|
||||
use middle::resolve::DefMap;
|
||||
use trans::adt;
|
||||
use trans::base::*;
|
||||
use trans::build::{AddCase, And, BitCast, Br, CondBr, GEPi, InBoundsGEP, Load};
|
||||
|
|
|
@ -2938,7 +2938,7 @@ pub fn crate_ctxt_to_encode_parms<'a, 'tcx>(cx: &'a SharedCrateContext<'tcx>,
|
|||
encoder::EncodeParams {
|
||||
diag: cx.sess().diagnostic(),
|
||||
tcx: cx.tcx(),
|
||||
reexports2: cx.exp_map2(),
|
||||
reexports: cx.export_map(),
|
||||
item_symbols: cx.item_symbols(),
|
||||
link_meta: cx.link_meta(),
|
||||
cstore: &cx.sess().cstore,
|
||||
|
@ -3071,7 +3071,7 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
|
|||
|
||||
pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
|
||||
-> (ty::ctxt<'tcx>, CrateTranslation) {
|
||||
let ty::CrateAnalysis { ty_cx: tcx, exp_map2, reachable, name, .. } = analysis;
|
||||
let ty::CrateAnalysis { ty_cx: tcx, export_map, reachable, name, .. } = analysis;
|
||||
let krate = tcx.map.krate();
|
||||
|
||||
// Before we touch LLVM, make sure that multithreading is enabled.
|
||||
|
@ -3098,7 +3098,7 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
|
|||
let shared_ccx = SharedCrateContext::new(link_meta.crate_name.as_slice(),
|
||||
codegen_units,
|
||||
tcx,
|
||||
exp_map2,
|
||||
export_map,
|
||||
Sha256::new(),
|
||||
link_meta.clone(),
|
||||
reachable);
|
||||
|
|
|
@ -13,7 +13,7 @@ use llvm::{ContextRef, ModuleRef, ValueRef, BuilderRef};
|
|||
use llvm::{TargetData};
|
||||
use llvm::mk_target_data;
|
||||
use metadata::common::LinkMeta;
|
||||
use middle::resolve;
|
||||
use middle::def::ExportMap;
|
||||
use middle::traits;
|
||||
use trans::adt;
|
||||
use trans::base;
|
||||
|
@ -61,7 +61,7 @@ pub struct SharedCrateContext<'tcx> {
|
|||
metadata_llmod: ModuleRef,
|
||||
metadata_llcx: ContextRef,
|
||||
|
||||
exp_map2: resolve::ExportMap2,
|
||||
export_map: ExportMap,
|
||||
reachable: NodeSet,
|
||||
item_symbols: RefCell<NodeMap<String>>,
|
||||
link_meta: LinkMeta,
|
||||
|
@ -238,7 +238,7 @@ impl<'tcx> SharedCrateContext<'tcx> {
|
|||
pub fn new(crate_name: &str,
|
||||
local_count: uint,
|
||||
tcx: ty::ctxt<'tcx>,
|
||||
emap2: resolve::ExportMap2,
|
||||
export_map: ExportMap,
|
||||
symbol_hasher: Sha256,
|
||||
link_meta: LinkMeta,
|
||||
reachable: NodeSet)
|
||||
|
@ -251,7 +251,7 @@ impl<'tcx> SharedCrateContext<'tcx> {
|
|||
local_ccxs: Vec::with_capacity(local_count),
|
||||
metadata_llmod: metadata_llmod,
|
||||
metadata_llcx: metadata_llcx,
|
||||
exp_map2: emap2,
|
||||
export_map: export_map,
|
||||
reachable: reachable,
|
||||
item_symbols: RefCell::new(NodeMap::new()),
|
||||
link_meta: link_meta,
|
||||
|
@ -329,8 +329,8 @@ impl<'tcx> SharedCrateContext<'tcx> {
|
|||
self.metadata_llcx
|
||||
}
|
||||
|
||||
pub fn exp_map2<'a>(&'a self) -> &'a resolve::ExportMap2 {
|
||||
&self.exp_map2
|
||||
pub fn export_map<'a>(&'a self) -> &'a ExportMap {
|
||||
&self.export_map
|
||||
}
|
||||
|
||||
pub fn reachable<'a>(&'a self) -> &'a NodeSet {
|
||||
|
@ -553,8 +553,8 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
|||
&self.local.item_vals
|
||||
}
|
||||
|
||||
pub fn exp_map2<'a>(&'a self) -> &'a resolve::ExportMap2 {
|
||||
&self.shared.exp_map2
|
||||
pub fn export_map<'a>(&'a self) -> &'a ExportMap {
|
||||
&self.shared.export_map
|
||||
}
|
||||
|
||||
pub fn reachable<'a>(&'a self) -> &'a NodeSet {
|
||||
|
|
|
@ -90,7 +90,6 @@ pub use rustc::session;
|
|||
pub use rustc::util;
|
||||
|
||||
use middle::def;
|
||||
use middle::resolve;
|
||||
use middle::infer;
|
||||
use middle::subst;
|
||||
use middle::subst::VecPerParamSpace;
|
||||
|
@ -121,7 +120,7 @@ struct TypeAndSubsts<'tcx> {
|
|||
|
||||
struct CrateCtxt<'a, 'tcx: 'a> {
|
||||
// A mapping from method call sites to traits that have that method.
|
||||
trait_map: resolve::TraitMap,
|
||||
trait_map: ty::TraitMap,
|
||||
tcx: &'a ty::ctxt<'tcx>
|
||||
}
|
||||
|
||||
|
@ -316,7 +315,7 @@ fn check_for_entry_fn(ccx: &CrateCtxt) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn check_crate(tcx: &ty::ctxt, trait_map: resolve::TraitMap) {
|
||||
pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
|
||||
let time_passes = tcx.sess.time_passes();
|
||||
let ccx = CrateCtxt {
|
||||
trait_map: trait_map,
|
||||
|
|
|
@ -24,7 +24,7 @@ impl BarTy {
|
|||
fn b(&self) {}
|
||||
}
|
||||
|
||||
// If these fail, it's necessary to update middle::resolve and the cfail tests.
|
||||
// If these fail, it's necessary to update rustc_resolve and the cfail tests.
|
||||
impl Foo for *const BarTy {
|
||||
fn bar(&self) {
|
||||
self.baz();
|
||||
|
@ -33,7 +33,7 @@ impl Foo for *const BarTy {
|
|||
}
|
||||
}
|
||||
|
||||
// If these fail, it's necessary to update middle::resolve and the cfail tests.
|
||||
// If these fail, it's necessary to update rustc_resolve and the cfail tests.
|
||||
impl<'a> Foo for &'a BarTy {
|
||||
fn bar(&self) {
|
||||
self.baz();
|
||||
|
@ -45,7 +45,7 @@ impl<'a> Foo for &'a BarTy {
|
|||
}
|
||||
}
|
||||
|
||||
// If these fail, it's necessary to update middle::resolve and the cfail tests.
|
||||
// If these fail, it's necessary to update rustc_resolve and the cfail tests.
|
||||
impl<'a> Foo for &'a mut BarTy {
|
||||
fn bar(&self) {
|
||||
self.baz();
|
||||
|
@ -57,7 +57,7 @@ impl<'a> Foo for &'a mut BarTy {
|
|||
}
|
||||
}
|
||||
|
||||
// If these fail, it's necessary to update middle::resolve and the cfail tests.
|
||||
// If these fail, it's necessary to update rustc_resolve and the cfail tests.
|
||||
impl Foo for Box<BarTy> {
|
||||
fn bar(&self) {
|
||||
self.baz();
|
||||
|
@ -65,7 +65,7 @@ impl Foo for Box<BarTy> {
|
|||
}
|
||||
}
|
||||
|
||||
// If these fail, it's necessary to update middle::resolve and the cfail tests.
|
||||
// If these fail, it's necessary to update rustc_resolve and the cfail tests.
|
||||
impl Foo for *const int {
|
||||
fn bar(&self) {
|
||||
self.baz();
|
||||
|
@ -73,7 +73,7 @@ impl Foo for *const int {
|
|||
}
|
||||
}
|
||||
|
||||
// If these fail, it's necessary to update middle::resolve and the cfail tests.
|
||||
// If these fail, it's necessary to update rustc_resolve and the cfail tests.
|
||||
impl<'a> Foo for &'a int {
|
||||
fn bar(&self) {
|
||||
self.baz();
|
||||
|
@ -81,7 +81,7 @@ impl<'a> Foo for &'a int {
|
|||
}
|
||||
}
|
||||
|
||||
// If these fail, it's necessary to update middle::resolve and the cfail tests.
|
||||
// If these fail, it's necessary to update rustc_resolve and the cfail tests.
|
||||
impl<'a> Foo for &'a mut int {
|
||||
fn bar(&self) {
|
||||
self.baz();
|
||||
|
@ -89,7 +89,7 @@ impl<'a> Foo for &'a mut int {
|
|||
}
|
||||
}
|
||||
|
||||
// If these fail, it's necessary to update middle::resolve and the cfail tests.
|
||||
// If these fail, it's necessary to update rustc_resolve and the cfail tests.
|
||||
impl Foo for Box<int> {
|
||||
fn bar(&self) {
|
||||
self.baz();
|
||||
|
|
Loading…
Reference in a new issue