Skip to content

Commit

Permalink
Load extern crates in resolve.
Browse files Browse the repository at this point in the history
  • Loading branch information
jseyfried committed Sep 23, 2016
1 parent 533c04d commit 7b5c59e
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 155 deletions.
2 changes: 0 additions & 2 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ pub enum DepNode<D: Clone + Debug> {
WorkProduct(Arc<WorkProductId>),

// Represents different phases in the compiler.
CrateReader,
CollectLanguageItems,
CheckStaticRecursion,
ResolveLifetimes,
Expand Down Expand Up @@ -171,7 +170,6 @@ impl<D: Clone + Debug> DepNode<D> {

match *self {
Krate => Some(Krate),
CrateReader => Some(CrateReader),
CollectLanguageItems => Some(CollectLanguageItems),
CheckStaticRecursion => Some(CheckStaticRecursion),
ResolveLifetimes => Some(ResolveLifetimes),
Expand Down
8 changes: 5 additions & 3 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -422,6 +422,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
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);
}
14 changes: 3 additions & 11 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ use rustc_back::sha2::{Sha256, Digest};
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;
Expand Down Expand Up @@ -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", || {
Expand Down Expand Up @@ -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));
Expand Down
183 changes: 74 additions & 109 deletions src/librustc_metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -31,20 +32,18 @@ use std::rc::Rc;
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> {
Expand All @@ -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| {
Expand Down Expand Up @@ -918,98 +910,22 @@ impl ExtensionCrate {
}
}

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

// 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();
}
creader: CrateReader::new(sess, cstore, crate_name, krate.config.clone()),
};

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) {
Expand Down Expand Up @@ -1073,13 +989,62 @@ impl<'a> LocalCrateReader<'a> {
}
}

/// 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)
}
}
33 changes: 8 additions & 25 deletions src/librustc_metadata/macro_import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ use std::collections::HashSet;
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;
Expand All @@ -31,31 +29,18 @@ use syntax::parse::token;
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> {
Expand Down Expand Up @@ -108,9 +93,7 @@ impl<'a> middle::cstore::MacroLoader for MacroLoader<'a> {

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,
Expand All @@ -129,7 +112,7 @@ impl<'a> MacroLoader<'a> {
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();

Expand Down
2 changes: 2 additions & 0 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ impl<'b> Resolver<'b> {

/// 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;
Expand Down
Loading

0 comments on commit 7b5c59e

Please sign in to comment.