diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index 97a912c4d9cb..b2c8380e130b 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -162,7 +162,7 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str, bind middle::ast_map::map_crate(*crate)); time(time_passes, "external crate/lib resolution", bind creader::read_crates(sess, *crate)); - let {def_map: def_map, ext_map: ext_map} = + let {def_map: def_map, ext_map: ext_map, exp_map: exp_map} = time(time_passes, "resolution", bind resolve::resolve_crate(sess, ast_map, crate)); let freevars = @@ -197,7 +197,7 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str, let (llmod, link_meta) = time(time_passes, "translation", bind trans::trans_crate(sess, crate, ty_cx, - outputs.obj_filename, ast_map, + outputs.obj_filename, exp_map, ast_map, mut_map, copy_map, last_uses)); time(time_passes, "LLVM passes", bind link::write::run_passes(sess, llmod, outputs.obj_filename)); @@ -267,7 +267,7 @@ fn pretty_print_input(sess: session::session, cfg: ast::crate_cfg, input: str, ppm_typed. { crate = syntax::ext::expand::expand_crate(sess, crate); let amap = middle::ast_map::map_crate(*crate); - let {def_map: def_map, ext_map: ext_map} = + let {def_map: def_map, ext_map: ext_map, exp_map: _exp_map} = resolve::resolve_crate(sess, amap, crate); let freevars = freevars::annotate_freevars(def_map, crate); let ty_cx = ty::mk_ctxt(sess, def_map, ext_map, amap, freevars); diff --git a/src/comp/metadata/csearch.rs b/src/comp/metadata/csearch.rs index 48b9774db519..222d6ac7f0e0 100644 --- a/src/comp/metadata/csearch.rs +++ b/src/comp/metadata/csearch.rs @@ -23,8 +23,33 @@ fn get_type_param_count(cstore: cstore::cstore, def: ast::def_id) -> uint { fn lookup_defs(cstore: cstore::cstore, cnum: ast::crate_num, path: [ast::ident]) -> [ast::def] { - let cdata = cstore::get_crate_data(cstore, cnum).data; - ret decoder::lookup_defs(cdata, cnum, path); + let result = []; + for (c, data, def) in resolve_path(cstore, cnum, path) { + result += [decoder::lookup_def(c, data, def)]; + } + ret result; +} + +fn resolve_path(cstore: cstore::cstore, cnum: ast::crate_num, + path: [ast::ident]) -> + [(ast::crate_num, @[u8], ast::def_id)] { + let cm = cstore::get_crate_data(cstore, cnum); + log #fmt("resolve_path %s in crates[%d]:%s", + str::connect(path, "::"), cnum, cm.name); + let result = []; + for def in decoder::resolve_path(path, cm.data) { + if def.crate == ast::local_crate { + result += [(cnum, cm.data, def)]; + } else { + if cm.cnum_map.contains_key(def.crate) { + // This reexport is itself a reexport from anther crate + let next_cnum = cm.cnum_map.get(def.crate); + let next_cm_data = cstore::get_crate_data(cstore, next_cnum); + result += [(next_cnum, next_cm_data.data, def)]; + } + } + } + ret result; } fn get_tag_variants(tcx: ty::ctxt, def: ast::def_id) -> [ty::variant_info] { diff --git a/src/comp/metadata/decoder.rs b/src/comp/metadata/decoder.rs index d5d981bb81c4..b4b9712b807e 100644 --- a/src/comp/metadata/decoder.rs +++ b/src/comp/metadata/decoder.rs @@ -15,7 +15,8 @@ export get_tag_variants; export get_type; export get_type_param_count; export get_type_param_kinds; -export lookup_defs; +export lookup_def; +export resolve_path; export get_crate_attributes; export list_crate_metadata; export crate_dep; @@ -158,14 +159,8 @@ fn resolve_path(path: [ast::ident], data: @[u8]) -> [ast::def_id] { ret result; } -// Crate metadata queries -fn lookup_defs(data: @[u8], cnum: ast::crate_num, path: [ast::ident]) -> - [ast::def] { - ret vec::map(bind lookup_def(cnum, data, _), resolve_path(path, data)); -} - -// FIXME doesn't yet handle re-exported externals +// FIXME doesn't yet handle renamed re-exported externals fn lookup_def(cnum: ast::crate_num, data: @[u8], did_: ast::def_id) -> ast::def { let item = lookup_item(did_.node, data); diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs index 150c241ff603..c013ec614edf 100644 --- a/src/comp/metadata/encoder.rs +++ b/src/comp/metadata/encoder.rs @@ -141,15 +141,28 @@ fn encode_module_item_paths(ebml_w: ebml::writer, module: _mod, path: [str], } } -fn encode_item_paths(ebml_w: ebml::writer, crate: @crate) -> [entry] { +fn encode_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt, crate: @crate) + -> [entry] { let index: [entry] = []; let path: [str] = []; ebml::start_tag(ebml_w, tag_paths); encode_module_item_paths(ebml_w, crate.node.module, path, index); + encode_reexport_paths(ebml_w, ecx, index); ebml::end_tag(ebml_w); ret index; } +fn encode_reexport_paths(ebml_w: ebml::writer, + ecx: @encode_ctxt, &index: [entry]) { + ecx.ccx.exp_map.items {|path, def| + index += [{val: path, pos: ebml_w.writer.tell()}]; + ebml::start_tag(ebml_w, tag_paths_data_item); + encode_name(ebml_w, path); + encode_def_id(ebml_w, ast_util::def_id_of_def(def)); + ebml::end_tag(ebml_w); + } +} + // Item info table encoding fn encode_family(ebml_w: ebml::writer, c: u8) { @@ -602,7 +615,7 @@ fn encode_metadata(cx: @crate_ctxt, crate: @crate) -> str { // Encode and index the paths. ebml::start_tag(ebml_w, tag_paths); - let paths_index = encode_item_paths(ebml_w, crate); + let paths_index = encode_item_paths(ebml_w, ecx, crate); let paths_buckets = create_index(paths_index, hash_path); encode_index(ebml_w, paths_buckets, write_str); ebml::end_tag(ebml_w); diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 55ff537d447a..73a12b569078 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -15,12 +15,13 @@ import core::{vec, option, str}; import std::list; import std::map::hashmap; import std::list::{list, nil, cons}; -import option::{some, none, is_none}; +import option::{some, none, is_none, is_some}; import syntax::print::pprust::*; export resolve_crate; export def_map; export ext_map; +export exp_map; // Resolving happens in two passes. The first pass collects defids of all // (internal) imports and modules, so that they can be looked up when needed, @@ -97,15 +98,17 @@ type indexed_mod = { type def_map = hashmap; type ext_map = hashmap; +type exp_map = hashmap; type env = {cstore: cstore::cstore, def_map: def_map, ast_map: ast_map::map, imports: hashmap, + exp_map: exp_map, mod_map: hashmap, block_map: hashmap, - ext_map: hashmap, + ext_map: ext_map, ext_cache: ext_hash, used_imports: {mutable track: bool, mutable data: [ast::node_id]}, @@ -121,12 +124,13 @@ tag dir { inside; outside; } tag namespace { ns_value; ns_type; ns_module; } fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) -> - {def_map: def_map, ext_map: ext_map} { + {def_map: def_map, ext_map: ext_map, exp_map: exp_map} { let e = @{cstore: sess.get_cstore(), def_map: new_int_hash(), ast_map: amap, imports: new_int_hash(), + exp_map: new_str_hash(), mod_map: new_int_hash(), block_map: new_int_hash(), ext_map: new_def_hash(), @@ -138,12 +142,12 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) -> map_crate(e, crate); resolve_imports(*e); check_for_collisions(e, *crate); - check_bad_exports(e); + check_exports(e); resolve_names(e, crate); if sess.get_opts().warn_unused_imports { check_unused_imports(e); } - ret {def_map: e.def_map, ext_map: e.ext_map}; + ret {def_map: e.def_map, ext_map: e.ext_map, exp_map: e.exp_map}; } // Locate all modules and imports and index them, so that the next passes can @@ -1527,15 +1531,50 @@ fn ensure_unique(e: env, sp: span, elts: [T], id: fn(T) -> ident, for elt: T in elts { add_name(ch, sp, id(elt)); } } -fn check_bad_exports(e: @env) { - fn lookup_glob_any(e: env, info: @indexed_mod, sp: span, ident: ident) -> - bool { - ret !option::is_none(lookup_glob_in_mod(e, info, sp, ident, ns_module, - inside)) || - !option::is_none(lookup_glob_in_mod(e, info, sp, ident, - ns_value, inside)) || - !option::is_none(lookup_glob_in_mod(e, info, sp, ident, - ns_type, inside)); +fn check_exports(e: @env) { + fn lookup_glob_any(e: @env, info: @indexed_mod, sp: span, path: str, + ident: ident) -> bool { + let lookup = + bind lookup_glob_in_mod(*e, info, sp, ident, _, inside); + let (m, v, t) = (lookup(ns_module), + lookup(ns_value), + lookup(ns_type)); + maybe_add_reexport(e, path + ident, m); + maybe_add_reexport(e, path + ident, v); + maybe_add_reexport(e, path + ident, t); + ret is_some(m) || is_some(v) || is_some(t); + } + + fn maybe_add_reexport(e: @env, path: str, def: option::t) { + if option::is_some(def) { + e.exp_map.insert(path, option::get(def)); + } + } + + fn check_export(e: @env, ident: str, val: @indexed_mod, vi: @view_item) { + if val.index.contains_key(ident) { + let xs = val.index.get(ident); + list::iter(xs) {|x| + alt x { + mie_import_ident(id, _) { + alt e.imports.get(id) { + resolved(v, t, m, rid, _) { + maybe_add_reexport(e, val.path + rid, v); + maybe_add_reexport(e, val.path + rid, t); + maybe_add_reexport(e, val.path + rid, m); + } + _ { } + } + } + _ { } + } + } + } else if lookup_glob_any(e, val, vi.span, val.path, ident) { + // do nothing + } else { + e.sess.span_warn(vi.span, + #fmt("exported item %s is not defined", ident)); + } } e.mod_map.values {|val| @@ -1545,12 +1584,7 @@ fn check_bad_exports(e: @env) { alt vi.node { ast::view_item_export(idents, _) { for ident in idents { - if !val.index.contains_key(ident) && - !lookup_glob_any(*e, val, vi.span, ident) { - e.sess.span_warn(vi.span, - "exported item " + ident + - " is not defined"); - } + check_export(e, ident, val, vi); } } _ { } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e9f769b4ec5d..79dc94483161 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -20,7 +20,7 @@ import std::map::{new_int_hash, new_str_hash}; import option::{some, none}; import driver::session; import front::attr; -import middle::{ty, gc}; +import middle::{ty, gc, resolve}; import middle::freevars::*; import back::{link, abi, upcall}; import syntax::{ast, ast_util}; @@ -5511,8 +5511,9 @@ fn write_abi_version(ccx: @crate_ctxt) { } fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt, - output: str, amap: ast_map::map, mut_map: mut::mut_map, - copy_map: alias::copy_map, last_uses: last_use::last_uses) + output: str, emap: resolve::exp_map, amap: ast_map::map, + mut_map: mut::mut_map, copy_map: alias::copy_map, + last_uses: last_use::last_uses) -> (ModuleRef, link::link_meta) { let sha = std::sha1::mk_sha1(); let link_meta = link::build_link_meta(sess, *crate, output, sha); @@ -5567,6 +5568,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt, intrinsics: intrinsics, item_ids: new_int_hash::(), ast_map: amap, + exp_map: emap, item_symbols: new_int_hash::(), mutable main_fn: none::, link_meta: link_meta, diff --git a/src/comp/middle/trans_common.rs b/src/comp/middle/trans_common.rs index 889ba2e44a12..7d9775a6c2a9 100644 --- a/src/comp/middle/trans_common.rs +++ b/src/comp/middle/trans_common.rs @@ -84,6 +84,7 @@ type crate_ctxt = intrinsics: hashmap, item_ids: hashmap, ast_map: ast_map::map, + exp_map: hashmap, item_symbols: hashmap, mutable main_fn: option::t, link_meta: link::link_meta,