Load extern crates in resolve.

This commit is contained in:
Jeffrey Seyfried 2016-09-16 02:52:09 +00:00
parent 533c04dbb3
commit 7b5c59ea65
8 changed files with 98 additions and 155 deletions

View File

@ -51,7 +51,6 @@ pub enum DepNode<D: Clone + Debug> {
WorkProduct(Arc<WorkProductId>),
// Represents different phases in the compiler.
CrateReader,
CollectLanguageItems,
CheckStaticRecursion,
ResolveLifetimes,
@ -171,7 +170,6 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
match *self {
Krate => Some(Krate),
CrateReader => Some(CrateReader),
CollectLanguageItems => Some(CollectLanguageItems),
CheckStaticRecursion => Some(CheckStaticRecursion),
ResolveLifetimes => Some(ResolveLifetimes),

View File

@ -25,7 +25,7 @@
use hir::def::{self, Def};
use hir::def_id::{CrateNum, DefId, DefIndex};
use hir::map as hir_map;
use hir::map::definitions::DefKey;
use hir::map::definitions::{Definitions, DefKey};
use hir::svh::Svh;
use middle::lang_items;
use ty::{self, Ty, TyCtxt};
@ -422,6 +422,8 @@ fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
}
pub trait MacroLoader {
fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<LoadedMacro>;
pub trait CrateLoader {
fn load_macros(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<LoadedMacro>;
fn process_item(&mut self, item: &ast::Item, defs: &Definitions);
fn postprocess(&mut self, krate: &ast::Crate);
}

View File

@ -28,8 +28,7 @@
use rustc_borrowck as borrowck;
use rustc_incremental::{self, IncrementalHashesMap};
use rustc_resolve::{MakeGlobMap, Resolver};
use rustc_metadata::macro_import;
use rustc_metadata::creader::read_local_crates;
use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::CStore;
use rustc_trans::back::{link, write};
use rustc_trans as trans;
@ -639,12 +638,10 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
}
sess.track_errors(|| sess.lint_store.borrow_mut().process_command_line(sess))?;
let mut macro_loader =
macro_import::MacroLoader::new(sess, &cstore, crate_name, krate.config.clone());
let mut crate_loader = CrateLoader::new(sess, &cstore, &krate, crate_name);
let resolver_arenas = Resolver::arenas();
let mut resolver =
Resolver::new(sess, &krate, make_glob_map, &mut macro_loader, &resolver_arenas);
Resolver::new(sess, &krate, make_glob_map, &mut crate_loader, &resolver_arenas);
syntax_ext::register_builtins(&mut resolver, sess.features.borrow().quote);
krate = time(time_passes, "expansion", || {
@ -736,11 +733,6 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
// Collect defintions for def ids.
time(sess.time_passes(), "collecting defs", || resolver.definitions.collect(&krate));
time(sess.time_passes(), "external crate/lib resolution", || {
let defs = &resolver.definitions;
read_local_crates(sess, &cstore, defs, &krate, crate_name, &sess.dep_graph)
});
time(sess.time_passes(),
"early lint checks",
|| lint::check_ast_crate(sess, &krate));

View File

@ -12,14 +12,15 @@
use cstore::{self, CStore, CrateSource, MetadataBlob};
use loader::{self, CratePaths};
use macro_import;
use schema::CrateRoot;
use rustc::hir::def_id::{CrateNum, DefIndex};
use rustc::hir::svh::Svh;
use rustc::dep_graph::{DepGraph, DepNode};
use rustc::session::{config, Session};
use rustc::session::config::PanicStrategy;
use rustc::session::search_paths::PathKind;
use rustc::middle;
use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
use rustc::util::nodemap::{FnvHashMap, FnvHashSet};
use rustc::hir::map as hir_map;
@ -31,20 +32,18 @@
use std::fs;
use syntax::ast;
use syntax::ext::base::LoadedMacro;
use syntax::abi::Abi;
use syntax::parse;
use syntax::attr;
use syntax::parse::token::InternedString;
use syntax::visit;
use syntax_pos::{self, Span, mk_sp};
use log;
struct LocalCrateReader<'a> {
sess: &'a Session,
pub struct CrateLoader<'a> {
pub sess: &'a Session,
pub creader: CrateReader<'a>,
cstore: &'a CStore,
creader: CrateReader<'a>,
krate: &'a ast::Crate,
definitions: &'a hir_map::Definitions,
}
pub struct CrateReader<'a> {
@ -56,13 +55,6 @@ pub struct CrateReader<'a> {
local_crate_config: ast::CrateConfig,
}
impl<'a> visit::Visitor for LocalCrateReader<'a> {
fn visit_item(&mut self, a: &ast::Item) {
self.process_item(a);
visit::walk_item(self, a);
}
}
fn dump_crates(cstore: &CStore) {
info!("resolved crates:");
cstore.iter_crate_data_origins(|_, data, opt_source| {
@ -918,98 +910,22 @@ fn register(self, creader: &mut CrateReader) {
}
}
impl<'a> LocalCrateReader<'a> {
fn new(sess: &'a Session,
cstore: &'a CStore,
defs: &'a hir_map::Definitions,
krate: &'a ast::Crate,
local_crate_name: &str)
-> LocalCrateReader<'a> {
LocalCrateReader {
impl<'a> CrateLoader<'a> {
pub fn new(sess: &'a Session, cstore: &'a CStore, krate: &ast::Crate, crate_name: &str)
-> Self {
let loader = CrateLoader {
sess: sess,
cstore: cstore,
creader: CrateReader::new(sess, cstore, local_crate_name, krate.config.clone()),
krate: krate,
definitions: defs,
}
}
creader: CrateReader::new(sess, cstore, crate_name, krate.config.clone()),
};
// Traverses an AST, reading all the information about use'd crates and
// extern libraries necessary for later resolving, typechecking, linking,
// etc.
fn read_crates(&mut self, dep_graph: &DepGraph) {
let _task = dep_graph.in_task(DepNode::CrateReader);
self.process_crate(self.krate);
visit::walk_crate(self, self.krate);
self.creader.inject_allocator_crate();
self.creader.inject_panic_runtime(self.krate);
if log_enabled!(log::INFO) {
dump_crates(&self.cstore);
}
for &(ref name, kind) in &self.sess.opts.libs {
register_native_lib(self.sess, self.cstore, None, name.clone(), kind);
}
self.creader.register_statically_included_foreign_items();
}
fn process_crate(&self, c: &ast::Crate) {
for a in c.attrs.iter().filter(|m| m.name() == "link_args") {
if let Some(ref linkarg) = a.value_str() {
self.cstore.add_used_link_args(&linkarg);
for attr in krate.attrs.iter().filter(|m| m.name() == "link_args") {
if let Some(ref linkarg) = attr.value_str() {
loader.cstore.add_used_link_args(&linkarg);
}
}
}
fn process_item(&mut self, i: &ast::Item) {
match i.node {
ast::ItemKind::ExternCrate(_) => {
// If this `extern crate` item has `#[macro_use]` then we can
// safely skip it. These annotations were processed during macro
// expansion and are already loaded (if necessary) into our
// crate store.
//
// Note that it's important we *don't* fall through below as
// some `#[macro_use]` crate are explicitly not linked (e.g.
// macro crates) so we want to ensure we avoid `resolve_crate`
// with those.
if attr::contains_name(&i.attrs, "macro_use") {
if self.cstore.was_used_for_derive_macros(i) {
return
}
}
if let Some(info) = self.creader.extract_crate_info(i) {
if !info.should_link {
return;
}
let (cnum, ..) = self.creader.resolve_crate(&None,
&info.ident,
&info.name,
None,
i.span,
PathKind::Crate,
true);
let def_id = self.definitions.opt_local_def_id(i.id).unwrap();
let len = self.definitions.def_path(def_id.index).data.len();
self.creader.update_extern_crate(cnum,
ExternCrate {
def_id: def_id,
span: i.span,
direct: true,
path_len: len,
},
&mut FnvHashSet());
self.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
}
}
ast::ItemKind::ForeignMod(ref fm) => self.process_foreign_mod(i, fm),
_ => { }
}
loader
}
fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod) {
@ -1073,13 +989,62 @@ fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod) {
}
}
/// Traverses an AST, reading all the information about use'd crates and extern
/// libraries necessary for later resolving, typechecking, linking, etc.
pub fn read_local_crates(sess: & Session,
cstore: & CStore,
defs: & hir_map::Definitions,
krate: & ast::Crate,
local_crate_name: &str,
dep_graph: &DepGraph) {
LocalCrateReader::new(sess, cstore, defs, krate, local_crate_name).read_crates(dep_graph)
impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
fn postprocess(&mut self, krate: &ast::Crate) {
self.creader.inject_allocator_crate();
self.creader.inject_panic_runtime(krate);
if log_enabled!(log::INFO) {
dump_crates(&self.cstore);
}
for &(ref name, kind) in &self.sess.opts.libs {
register_native_lib(self.sess, self.cstore, None, name.clone(), kind);
}
self.creader.register_statically_included_foreign_items();
}
fn process_item(&mut self, item: &ast::Item, definitions: &hir_map::Definitions) {
match item.node {
ast::ItemKind::ExternCrate(_) => {}
ast::ItemKind::ForeignMod(ref fm) => return self.process_foreign_mod(item, fm),
_ => return,
}
// If this `extern crate` item has `#[macro_use]` then we can safely skip it.
// These annotations were processed during macro expansion and are already loaded
// (if necessary) into our crate store.
//
// Note that it's important we *don't* fall through below as some `#[macro_use]`
// crates are explicitly not linked (e.g. macro crates) so we want to ensure
// we avoid `resolve_crate` with those.
if attr::contains_name(&item.attrs, "macro_use") {
if self.cstore.was_used_for_derive_macros(item) {
return
}
}
if let Some(info) = self.creader.extract_crate_info(item) {
if !info.should_link {
return;
}
let (cnum, ..) = self.creader.resolve_crate(
&None, &info.ident, &info.name, None, item.span, PathKind::Crate, true,
);
let def_id = definitions.opt_local_def_id(item.id).unwrap();
let len = definitions.def_path(def_id.index).data.len();
let extern_crate =
ExternCrate { def_id: def_id, span: item.span, direct: true, path_len: len };
self.creader.update_extern_crate(cnum, extern_crate, &mut FnvHashSet());
self.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
}
}
fn load_macros(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<LoadedMacro> {
macro_import::load_macros(self, extern_crate, allows_macros)
}
}

View File

@ -14,11 +14,9 @@
use std::env;
use std::mem;
use creader::{CrateReader, Macros};
use cstore::CStore;
use creader::{CrateLoader, Macros};
use rustc::hir::def_id::DefIndex;
use rustc::middle;
use rustc::session::Session;
use rustc::util::nodemap::FnvHashMap;
use rustc_back::dynamic_lib::DynamicLibrary;
@ -31,31 +29,18 @@
use syntax_ext::deriving::custom::CustomDerive;
use syntax_pos::Span;
pub struct MacroLoader<'a> {
sess: &'a Session,
reader: CrateReader<'a>,
}
impl<'a> MacroLoader<'a> {
pub fn new(sess: &'a Session,
cstore: &'a CStore,
crate_name: &str,
crate_config: ast::CrateConfig)
-> MacroLoader<'a> {
MacroLoader {
sess: sess,
reader: CrateReader::new(sess, cstore, crate_name, crate_config),
}
}
}
pub fn call_bad_macro_reexport(a: &Session, b: Span) {
span_err!(a, b, E0467, "bad macro reexport");
}
pub type MacroSelection = FnvHashMap<token::InternedString, Span>;
impl<'a> middle::cstore::MacroLoader for MacroLoader<'a> {
pub fn load_macros(loader: &mut CrateLoader, extern_crate: &ast::Item, allows_macros: bool)
-> Vec<LoadedMacro> {
loader.load_crate(extern_crate, allows_macros)
}
impl<'a> CrateLoader<'a> {
fn load_crate(&mut self,
extern_crate: &ast::Item,
allows_macros: bool) -> Vec<LoadedMacro> {
@ -108,9 +93,7 @@ fn load_crate(&mut self,
self.load_macros(extern_crate, allows_macros, import, reexport)
}
}
impl<'a> MacroLoader<'a> {
fn load_macros<'b>(&mut self,
vi: &ast::Item,
allows_macros: bool,
@ -129,7 +112,7 @@ fn load_macros<'b>(&mut self,
return Vec::new();
}
let mut macros = self.reader.read_macros(vi);
let mut macros = self.creader.read_macros(vi);
let mut ret = Vec::new();
let mut seen = HashSet::new();

View File

@ -79,6 +79,8 @@ fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
/// Constructs the reduced graph for one item.
fn build_reduced_graph_for_item(&mut self, item: &Item) {
self.crate_loader.process_item(item, &self.definitions);
let parent = self.current_module;
let name = item.ident.name;
let sp = item.span;

View File

@ -44,7 +44,7 @@
use rustc::hir::map::Definitions;
use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr};
use rustc::middle::cstore::MacroLoader;
use rustc::middle::cstore::CrateLoader;
use rustc::session::Session;
use rustc::lint;
use rustc::hir::def::*;
@ -1066,7 +1066,7 @@ pub struct Resolver<'a> {
dummy_binding: &'a NameBinding<'a>,
new_import_semantics: bool, // true if `#![feature(item_like_imports)]`
macro_loader: &'a mut MacroLoader,
crate_loader: &'a mut CrateLoader,
macro_names: FnvHashSet<Name>,
// Maps the `Mark` of an expansion to its containing module or block.
@ -1172,7 +1172,7 @@ impl<'a> Resolver<'a> {
pub fn new(session: &'a Session,
krate: &Crate,
make_glob_map: MakeGlobMap,
macro_loader: &'a mut MacroLoader,
crate_loader: &'a mut CrateLoader,
arenas: &'a ResolverArenas<'a>)
-> Resolver<'a> {
let root_def = Def::Mod(DefId::local(CRATE_DEF_INDEX));
@ -1240,7 +1240,7 @@ pub fn new(session: &'a Session,
}),
new_import_semantics: session.features.borrow().item_like_imports,
macro_loader: macro_loader,
crate_loader: crate_loader,
macro_names: FnvHashSet(),
expansion_data: expansion_data,
}
@ -1263,6 +1263,7 @@ pub fn resolve_crate(&mut self, krate: &Crate) {
check_unused::check_crate(self, krate);
self.report_errors();
self.crate_loader.postprocess(krate);
}
fn new_module(&self, parent: Module<'a>, kind: ModuleKind, local: bool) -> Module<'a> {

View File

@ -38,7 +38,7 @@ struct ModuleData {
impl<'a> base::Resolver for Resolver<'a> {
fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<LoadedMacro> {
self.macro_loader.load_crate(extern_crate, allows_macros)
self.crate_loader.load_macros(extern_crate, allows_macros)
}
fn next_node_id(&mut self) -> ast::NodeId {