//! from rustc::middle::cstore in no particular order.
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
+use ich::StableHashingContext;
use middle;
});
impl_stable_hash_for!(struct middle::cstore::ExternCrate {
- def_id,
+ src,
span,
- direct,
- path_len
+ direct
});
+impl<'a> HashStable<StableHashingContext<'a>> for middle::cstore::ExternCrateSource {
+ fn hash_stable<W: StableHasherResult>(
+ &self,
+ hcx: &mut StableHashingContext<'a>,
+ hasher: &mut StableHasher<W>,
+ ) {
+ use middle::cstore::ExternCrateSource::*;
+
+ ::std::mem::discriminant(self).hash_stable(hcx, hasher);
+
+ match *self {
+ Extern { def_id, path_len } => {
+ def_id.hash_stable(hcx, hasher);
+ path_len.hash_stable(hcx, hasher);
+ }
+ Use { path_len } => path_len.hash_stable(hcx, hasher),
+ Path => {}
+ }
+ }
+}
+
impl_stable_hash_for!(struct middle::cstore::CrateSource {
dylib,
rlib,
#[derive(Copy, Clone, Debug)]
pub struct ExternCrate {
- /// def_id of an `extern crate` in the current crate that caused
- /// this crate to be loaded; note that there could be multiple
- /// such ids
- pub def_id: DefId,
+ pub src: ExternCrateSource,
/// span of the extern crate that caused this to be loaded
pub span: Span,
/// crate referenced above. If false, then this crate is a dep
/// of the crate.
pub direct: bool,
+}
- /// Number of links to reach the extern crate `def_id`
- /// declaration; used to select the extern crate with the shortest
- /// path
- pub path_len: usize,
+#[derive(Copy, Clone, Debug)]
+pub enum ExternCrateSource {
+ /// Crate is loaded by `extern crate`.
+ Extern {
+ /// def_id of the item in the current crate that caused
+ /// this crate to be loaded; note that there could be multiple
+ /// such ids
+ def_id: DefId,
+
+ /// Number of links to reach the extern crate `def_id`
+ /// declaration; used to select the extern crate with the shortest
+ /// path
+ path_len: usize,
+ },
+ // Crate is loaded by `use`.
+ Use {
+ path_len: usize,
+ },
+ /// Crate is implicitly loaded by an absolute or an `extern::` path.
+ Path,
}
pub struct EncodedMetadata {
}
pub trait CrateLoader {
- fn process_item(&mut self, item: &ast::Item, defs: &Definitions);
+ fn process_extern_crate(&mut self, item: &ast::Item, defs: &Definitions) -> CrateNum;
+
+ fn process_path_extern(
+ &mut self,
+ name: Symbol,
+ span: Span,
+ ) -> CrateNum;
+
+ fn process_use_extern(
+ &mut self,
+ name: Symbol,
+ span: Span,
+ id: ast::NodeId,
+ defs: &Definitions,
+ ) -> CrateNum;
+
fn postprocess(&mut self, krate: &ast::Crate);
- fn resolve_crate_from_path(&mut self, name: Symbol, span: Span) -> CrateNum;
}
// This method is used when generating the command line to pass through to
use hir::map::DefPathData;
use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use ty::{self, Ty, TyCtxt};
+use middle::cstore::{ExternCrate, ExternCrateSource};
use syntax::ast;
use syntax::symbol::Symbol;
use syntax::symbol::InternedString;
// `extern crate` manually, we put the `extern
// crate` as the parent. So you wind up with
// something relative to the current crate.
- // 2. for an indirect crate, where there is no extern
- // crate, we just prepend the crate name.
+ // 2. for an extern inferred from a path or an indirect crate,
+ // where there is no explicit `extern crate`, we just prepend
+ // the crate name.
//
// Returns `None` for the local crate.
if cnum != LOCAL_CRATE {
let opt_extern_crate = self.extern_crate(cnum.as_def_id());
- let opt_extern_crate = opt_extern_crate.and_then(|extern_crate| {
- if extern_crate.direct {
- Some(extern_crate.def_id)
- } else {
- None
- }
- });
- if let Some(extern_crate_def_id) = opt_extern_crate {
- self.push_item_path(buffer, extern_crate_def_id);
+ if let Some(ExternCrate {
+ src: ExternCrateSource::Extern { def_id, .. },
+ direct: true,
+ ..
+ }) = *opt_extern_crate
+ {
+ self.push_item_path(buffer, def_id);
} else {
buffer.push(&self.crate_name(cnum).as_str());
}
// followed by the path to the item within the crate and return.
if cur_def.index == CRATE_DEF_INDEX {
match *self.extern_crate(cur_def) {
- Some(ref extern_crate) if extern_crate.direct => {
- self.push_item_path(buffer, extern_crate.def_id);
- cur_path.iter().rev().map(|segment| buffer.push(&segment)).count();
+ Some(ExternCrate {
+ src: ExternCrateSource::Extern { def_id, .. },
+ direct: true,
+ ..
+ }) => {
+ self.push_item_path(buffer, def_id);
+ cur_path.iter().rev().for_each(|segment| buffer.push(&segment));
return true;
}
None => {
buffer.push(&self.crate_name(cur_def.krate).as_str());
- cur_path.iter().rev().map(|segment| buffer.push(&segment)).count();
+ cur_path.iter().rev().for_each(|segment| buffer.push(&segment));
return true;
}
_ => {},
use rustc_back::target::TargetTriple;
use rustc::session::search_paths::PathKind;
use rustc::middle;
-use rustc::middle::cstore::{validate_crate_name, ExternCrate};
+use rustc::middle::cstore::{validate_crate_name, ExternCrate, ExternCrateSource};
use rustc::util::common::record_time;
use rustc::util::nodemap::FxHashSet;
use rustc::hir::map::Definitions;
let cmeta = self.cstore.get_crate_data(cnum);
let mut old_extern_crate = cmeta.extern_crate.borrow_mut();
+ fn path_len_reverse(src: ExternCrateSource) -> cmp::Reverse<usize> {
+ cmp::Reverse(match src {
+ ExternCrateSource::Extern { path_len, .. } |
+ ExternCrateSource::Use { path_len } => path_len,
+ _ => usize::max_value(),
+ })
+ }
+
// Prefer:
// - something over nothing (tuple.0);
// - direct extern crate to indirect (tuple.1);
// - shorter paths to longer (tuple.2).
- let new_rank = (true, extern_crate.direct, !extern_crate.path_len);
+ let new_rank = (
+ true,
+ extern_crate.direct,
+ path_len_reverse(extern_crate.src),
+ );
let old_rank = match *old_extern_crate {
- None => (false, false, !0),
- Some(ref c) => (true, c.direct, !c.path_len),
+ None => (false, false, cmp::Reverse(usize::max_value())),
+ Some(ref c) => (
+ true,
+ c.direct,
+ path_len_reverse(c.src),
+ ),
};
-
if old_rank >= new_rank {
return; // no change needed
}
}
}
- fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) {
+ fn process_extern_crate(&mut self, item: &ast::Item, definitions: &Definitions) -> CrateNum {
match item.node {
ast::ItemKind::ExternCrate(orig_name) => {
debug!("resolving extern crate stmt. ident: {} orig_name: {:?}",
let def_id = definitions.opt_local_def_id(item.id).unwrap();
let path_len = definitions.def_path(def_id.index).data.len();
-
- let extern_crate = ExternCrate { def_id, span: item.span, direct: true, path_len };
- self.update_extern_crate(cnum, extern_crate, &mut FxHashSet());
+ self.update_extern_crate(
+ cnum,
+ ExternCrate {
+ src: ExternCrateSource::Extern { def_id, path_len },
+ span: item.span,
+ direct: true,
+ },
+ &mut FxHashSet(),
+ );
self.cstore.add_extern_mod_stmt_cnum(item.id, cnum);
+ cnum
}
- _ => {}
+ _ => bug!(),
}
}
- fn resolve_crate_from_path(&mut self, name: Symbol, span: Span) -> CrateNum {
- self.resolve_crate(&None, name, name, None, None, span, PathKind::Crate,
- DepKind::Explicit).0
+ fn process_path_extern(
+ &mut self,
+ name: Symbol,
+ span: Span,
+ ) -> CrateNum {
+ let cnum = self.resolve_crate(
+ &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit
+ ).0;
+
+ self.update_extern_crate(
+ cnum,
+ ExternCrate {
+ src: ExternCrateSource::Path,
+ span,
+ direct: true,
+ },
+ &mut FxHashSet(),
+ );
+
+ cnum
+ }
+
+ fn process_use_extern(
+ &mut self,
+ name: Symbol,
+ span: Span,
+ id: ast::NodeId,
+ definitions: &Definitions,
+ ) -> CrateNum {
+ let cnum = self.resolve_crate(
+ &None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit
+ ).0;
+
+ let def_id = definitions.opt_local_def_id(id).unwrap();
+ let path_len = definitions.def_path(def_id.index).data.len();
+
+ self.update_extern_crate(
+ cnum,
+ ExternCrate {
+ src: ExternCrateSource::Use { path_len },
+ span,
+ direct: true,
+ },
+ &mut FxHashSet(),
+ );
+
+ cnum
}
}
}
ItemKind::ExternCrate(orig_name) => {
- self.crate_loader.process_item(item, &self.definitions);
-
- // n.b. we don't need to look at the path option here, because cstore already did
- let crate_id = self.cstore.extern_mod_stmt_cnum_untracked(item.id).unwrap();
+ let crate_id = self.crate_loader.process_extern_crate(item, &self.definitions);
let module =
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
self.populate_module_if_necessary(module);
self.current_module = module;
}
- ItemKind::ForeignMod(..) => self.crate_loader.process_item(item, &self.definitions),
+ // Handled in `rustc_metadata::{native_libs,link_args}`
+ ItemKind::ForeignMod(..) => {}
// These items live in the value namespace.
ItemKind::Static(_, m, _) => {
prev_name == keywords::CrateRoot.name() &&
self.session.features_untracked().extern_absolute_paths {
// `::extern_crate::a::b`
- let crate_id = self.crate_loader.resolve_crate_from_path(name, ident.span);
+ let crate_id = self.crate_loader.process_path_extern(name, ident.span);
let crate_root =
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
self.populate_module_if_necessary(crate_root);
}
} else if is_extern && !token::is_path_segment_keyword(source) {
let crate_id =
- self.crate_loader.resolve_crate_from_path(source.name, directive.span);
+ self.resolver.crate_loader.process_use_extern(
+ source.name,
+ directive.span,
+ directive.id,
+ &self.resolver.definitions,
+ );
let crate_root =
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
self.populate_module_if_necessary(crate_root);
use rustc::hir::def::Def as HirDef;
use rustc::hir::map::{Node, NodeItem};
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::middle::cstore::ExternCrate;
use rustc::session::config::CrateType::CrateTypeExecutable;
use rustc::ty::{self, TyCtxt};
use rustc_typeck::hir_ty_to_ty;
for &n in self.tcx.crates().iter() {
let span = match *self.tcx.extern_crate(n.as_def_id()) {
- Some(ref c) => c.span,
+ Some(ExternCrate { span, .. }) => span,
None => {
- debug!("Skipping crate {}, no data", n);
- continue;
+ bug!("no data for crate {}", n);
}
};
let lo_loc = self.span_utils.sess.codemap().lookup_char_pos(span.lo());