auto merge of #19995 : eddyb/rust/split-resolve, r=nikomatsakis

r? @nikomatsakis
This commit is contained in:
bors 2014-12-20 05:52:18 +00:00
commit 8443b09e36
23 changed files with 565 additions and 475 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View 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);
}

View file

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

View 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);
}

View file

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

View file

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

View file

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

View file

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

View file

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