Extend ExternCrate to cover externs inferred from use or paths
This commit is contained in:
parent
4b9b70c394
commit
bbed61d3d2
8 changed files with 173 additions and 51 deletions
|
|
@ -12,6 +12,7 @@
|
|||
//! from rustc::middle::cstore in no particular order.
|
||||
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
|
||||
use ich::StableHashingContext;
|
||||
|
||||
use middle;
|
||||
|
||||
|
|
@ -47,12 +48,32 @@ impl_stable_hash_for!(enum middle::cstore::LinkagePreference {
|
|||
});
|
||||
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -148,10 +148,7 @@ pub enum LoadedMacro {
|
|||
|
||||
#[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,
|
||||
|
|
@ -160,11 +157,28 @@ pub struct ExternCrate {
|
|||
/// 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 {
|
||||
|
|
@ -357,9 +371,23 @@ impl CrateStore for DummyCrateStore {
|
|||
}
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
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;
|
||||
|
|
@ -95,21 +96,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
// `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());
|
||||
}
|
||||
|
|
@ -137,14 +137,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
// 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;
|
||||
}
|
||||
_ => {},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue