Extend ExternCrate to cover externs inferred from use or paths

This commit is contained in:
Shotaro Yamada 2018-04-10 23:01:24 +09:00
parent 4b9b70c394
commit bbed61d3d2
8 changed files with 173 additions and 51 deletions

View file

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

View file

@ -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

View file

@ -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;
}
_ => {},