rustc: Always resolve reexported names from original def

Issue #1501
This commit is contained in:
Haitao Li 2012-01-21 02:45:25 +08:00
parent a303fd98c7
commit 635e8200e1
4 changed files with 64 additions and 33 deletions

View File

@ -1,6 +1,7 @@
// Searching for information from the cstore
import syntax::ast;
import syntax::ast_util;
import middle::ty;
import option::{some, none};
import driver::session;
@ -12,7 +13,6 @@ export get_tag_variants;
export get_impls_for_mod;
export get_iface_methods;
export get_type;
export get_item_name;
export get_impl_iface;
fn get_symbol(cstore: cstore::cstore, def: ast::def_id) -> str {
@ -81,11 +81,6 @@ fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty {
decoder::get_type(cdata, def.node, tcx)
}
fn get_item_name(cstore: cstore::cstore, cnum: int, id: int) -> ast::ident {
let cdata = cstore::get_crate_data(cstore, cnum).data;
ret decoder::lookup_item_name(cdata, id);
}
fn get_impl_iface(tcx: ty::ctxt, def: ast::def_id)
-> option::t<ty::t> {
let cstore = tcx.sess.cstore;

View File

@ -4,6 +4,7 @@
import core::{vec, str};
import std::map;
import syntax::ast;
import util::common::*;
export cstore;
export cnum_map;
@ -22,6 +23,7 @@ export get_used_link_args;
export add_use_stmt_cnum;
export get_use_stmt_cnum;
export get_dep_hashes;
export get_path;
// A map from external crate numbers (as decoded from some crate file) to
@ -30,6 +32,11 @@ export get_dep_hashes;
// own crate numbers.
type cnum_map = map::hashmap<ast::crate_num, ast::crate_num>;
// Multiple items may have the same def_id in crate metadata. They may be
// renamed imports or reexports. This map keeps the "real" module path
// and def_id.
type mod_path_map = map::hashmap<ast::def_id, str>;
type crate_metadata = @{name: str,
data: @[u8],
cnum_map: cnum_map,
@ -45,6 +52,7 @@ enum cstore { private(cstore_private), }
type cstore_private =
@{metas: map::hashmap<ast::crate_num, crate_metadata>,
use_crate_map: use_crate_map,
mod_path_map: mod_path_map,
mutable used_crate_files: [str],
mutable used_libraries: [str],
mutable used_link_args: [str]};
@ -58,8 +66,10 @@ fn p(cstore: cstore) -> cstore_private { alt cstore { private(p) { p } } }
fn mk_cstore() -> cstore {
let meta_cache = map::new_int_hash::<crate_metadata>();
let crate_map = map::new_int_hash::<ast::crate_num>();
let mod_path_map = new_def_hash();
ret private(@{metas: meta_cache,
use_crate_map: crate_map,
mod_path_map: mod_path_map,
mutable used_crate_files: [],
mutable used_libraries: [],
mutable used_link_args: []});
@ -72,6 +82,11 @@ fn get_crate_data(cstore: cstore, cnum: ast::crate_num) -> crate_metadata {
fn set_crate_data(cstore: cstore, cnum: ast::crate_num,
data: crate_metadata) {
p(cstore).metas.insert(cnum, data);
vec::iter(decoder::get_crate_module_paths(data.data)) {|dp|
let (did, path) = dp;
let d = {crate: cnum, node: did.node};
p(cstore).mod_path_map.insert(d, path);
}
}
fn have_crate_data(cstore: cstore, cnum: ast::crate_num) -> bool {
@ -144,6 +159,13 @@ fn get_dep_hashes(cstore: cstore) -> [str] {
fn mapper(ch: crate_hash) -> str { ret ch.hash; }
ret vec::map(sorted, mapper);
}
fn get_path(cstore: cstore, d: ast::def_id) -> [str] {
alt p(cstore).mod_path_map.find(d) {
option::some(ds) { str::split_str(ds, "::") }
option::none { [] }
}
}
// Local Variables:
// mode: rust
// fill-column: 78;

View File

@ -1,6 +1,6 @@
// Decoding metadata from a single crate's metadata
import std::{ebml, io};
import std::{ebml, map, io};
import io::writer_util;
import syntax::{ast, ast_util};
import front::attr;
@ -26,6 +26,8 @@ export get_crate_deps;
export get_crate_hash;
export get_impls_for_mod;
export get_iface_methods;
export get_crate_module_paths;
// A function that takes a def_id relative to the crate being searched and
// returns a def_id relative to the compilation environment, i.e. if we hit a
// def_id for an item defined in another crate, somebody needs to figure out
@ -451,8 +453,16 @@ fn get_crate_hash(data: @[u8]) -> str {
fn list_crate_items(bytes: @[u8], md: ebml::doc, out: io::writer) {
out.write_str("=Items=\n");
let paths = ebml::get_doc(md, tag_paths);
let items = ebml::get_doc(md, tag_items);
iter_crate_items(bytes) {|path, did|
out.write_str(#fmt["%s (%s)\n", path, describe_def(items, did)]);
}
out.write_str("\n");
}
fn iter_crate_items(bytes: @[u8], proc: block(str, ast::def_id)) {
let md = ebml::new_doc(bytes);
let paths = ebml::get_doc(md, tag_paths);
let index = ebml::get_doc(paths, tag_index);
let bs = ebml::get_doc(index, tag_index_buckets);
ebml::tagged_docs(bs, tag_index_buckets_bucket) {|bucket|
@ -462,11 +472,35 @@ fn list_crate_items(bytes: @[u8], md: ebml::doc, out: io::writer) {
let def = ebml::doc_at(bytes, data.pos);
let did_doc = ebml::get_doc(def, tag_def_id);
let did = parse_def_id(ebml::doc_data(did_doc));
out.write_str(#fmt["%s (%s)\n", data.path,
describe_def(items, did)]);
proc(data.path, did);
};
};
out.write_str("\n");
}
fn get_crate_module_paths(bytes: @[u8]) -> [(ast::def_id, str)] {
fn mod_of_path(p: str) -> str {
str::connect(vec::init(str::split_str(p, "::")), "::")
}
// find all module (path, def_ids), which are not
// fowarded path due to renamed import or reexport
let res = [];
let mods = map::new_str_hash();
iter_crate_items(bytes) {|path, did|
let m = mod_of_path(path);
if str::is_not_empty(m) {
// if m has a sub-item, it must be a module
mods.insert(m, true);
}
// Collect everything by now. There might be multiple
// paths pointing to the same did. Those will be
// unified later by using the mods map
res += [(did, path)];
}
ret vec::filter(res) {|x|
let (_, xp) = x;
mods.contains_key(xp)
}
}
fn list_crate_metadata(bytes: @[u8], out: io::writer) {

View File

@ -1187,7 +1187,7 @@ fn lookup_in_mod(e: env, m: def, sp: span, name: ident, ns: namespace,
if !is_none(cached) { ret cached; }
let path = [name];
if defid.node != ast::crate_node_id {
path = e.ext_map.get(defid) + path;
path = cstore::get_path(e.cstore, defid) + path;
}
let fnd = lookup_external(e, defid.crate, path, ns);
if !is_none(fnd) {
@ -1484,27 +1484,7 @@ fn ns_ok(wanted:namespace, actual:namespace) -> bool {
fn lookup_external(e: env, cnum: int, ids: [ident], ns: namespace) ->
option::t<def> {
for d: def in csearch::lookup_defs(e.sess.cstore, cnum, ids) {
let did = def_id_of_def(d);
alt d {
def_mod(_) | def_native_mod(_) {
// The [native] module name might have renamed when importing,
// find the original name for further lookup of names inside the
// [native] module
if did.crate != ast::local_crate {
let cname = cstore::get_crate_data(e.cstore, did.crate).name;
let name =
csearch::get_item_name(e.cstore, did.crate, did.node);
#debug("lookup_external: %s %d, %d, %s, %s", cname,
did.crate, did.node, str::connect(ids, "::"), name);
e.ext_map.insert(did, vec::init(ids) + [name]);
} else {
e.ext_map.insert(did, ids);
}
}
_ {
e.ext_map.insert(did, ids);
}
}
e.ext_map.insert(def_id_of_def(d), ids);
if ns_ok(ns, ns_for_def(d)) { ret some(d); }
}
ret none::<def>;