Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load extern crates in resolve #36525

Merged
merged 1 commit into from
Sep 24, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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