diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs index 5f21d46adc9..1fe4c5085bc 100644 --- a/src/rustc/driver/driver.rs +++ b/src/rustc/driver/driver.rs @@ -176,6 +176,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, let { def_map: def_map, exp_map: exp_map, + exp_map2: exp_map2, impl_map: impl_map, trait_map: trait_map } = time(time_passes, ~"resolution", || @@ -238,7 +239,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, let (llmod, link_meta) = time(time_passes, ~"translation", || trans::base::trans_crate(sess, crate, ty_cx, outputs.obj_filename, - exp_map, maps)); + exp_map, exp_map2, maps)); time(time_passes, ~"LLVM passes", || link::write::run_passes(sess, llmod, outputs.obj_filename)); diff --git a/src/rustc/metadata.rs b/src/rustc/metadata.rs index 609f2af38dd..0744430b844 100644 --- a/src/rustc/metadata.rs +++ b/src/rustc/metadata.rs @@ -5,6 +5,8 @@ mod middle { import ty = middle_::ty; export ty; + import resolve3 = middle_::resolve3; + export resolve3; } mod front { diff --git a/src/rustc/metadata/common.rs b/src/rustc/metadata/common.rs index 8f97c204611..d65fa3a617f 100644 --- a/src/rustc/metadata/common.rs +++ b/src/rustc/metadata/common.rs @@ -100,6 +100,12 @@ impl items contain tag_item_impl_method elements, and classes const tag_item_trait_method_self_ty: uint = 0x4b; const tag_item_trait_method_self_ty_region: uint = 0x4c; +// Reexports are found within module tags. Each reexport contains def_ids +// and names. +const tag_items_data_item_reexport: uint = 0x4d; +const tag_items_data_item_reexport_def_id: uint = 0x4e; +const tag_items_data_item_reexport_name: uint = 0x4f; + // used to encode crate_ctxt side tables enum astencode_tag { // Reserves 0x50 -- 0x6f tag_ast = 0x50, @@ -115,15 +121,15 @@ enum astencode_tag { // Reserves 0x50 -- 0x6f tag_table_node_type = 0x57, tag_table_node_type_subst = 0x58, tag_table_freevars = 0x59, - tag_table_tcache, - tag_table_param_bounds, - tag_table_inferred_modes, - tag_table_mutbl, - tag_table_last_use, - tag_table_spill, - tag_table_method_map, - tag_table_vtable_map, - tag_table_borrowings + tag_table_tcache = 0x5a, + tag_table_param_bounds = 0x5b, + tag_table_inferred_modes = 0x5c, + tag_table_mutbl = 0x5d, + tag_table_last_use = 0x5e, + tag_table_spill = 0x5f, + tag_table_method_map = 0x60, + tag_table_vtable_map = 0x61, + tag_table_borrowings = 0x62 } // djb's cdb hashes. diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index c36b99ba9d5..3c917e8b3d5 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -127,6 +127,14 @@ fn item_def_id(d: ebml::doc, cdata: cmd) -> ast::def_id { |d| parse_def_id(d))); } +fn each_reexport(d: ebml::doc, f: fn(ebml::doc) -> bool) { + for ebml::tagged_docs(d, tag_items_data_item_reexport) |reexport_doc| { + if !f(reexport_doc) { + return; + } + } +} + fn field_mutability(d: ebml::doc) -> ast::class_mutability { // Use maybe_get_doc in case it's a method option::map_default( @@ -426,22 +434,67 @@ fn each_path(cdata: cmd, f: fn(path_entry) -> bool) { // First, go through all the explicit items. for ebml::tagged_docs(items_data, tag_items_data_item) |item_doc| { if !broken { - let name = ast_map::path_to_str_with_sep(item_path(item_doc), + let path = ast_map::path_to_str_with_sep(item_path(item_doc), ~"::"); - if name != ~"" { + if path != ~"" { // Extract the def ID. let def_id = item_def_id(item_doc, cdata); // Construct the def for this item. - debug!{"(each_path) yielding explicit item: %s", name}; + debug!{"(each_path) yielding explicit item: %s", path}; let def_like = item_to_def_like(item_doc, def_id, cdata.cnum); // Hand the information off to the iteratee. - let this_path_entry = path_entry(name, def_like); + let this_path_entry = path_entry(path, def_like); if !f(this_path_entry) { broken = true; // XXX: This is awful. } } + + // If this is a module, find the reexports. + for each_reexport(item_doc) |reexport_doc| { + if !broken { + let def_id_doc = + ebml::get_doc(reexport_doc, + tag_items_data_item_reexport_def_id); + let def_id = + ebml::with_doc_data(def_id_doc, |d| parse_def_id(d)); + let def_id = translate_def_id(cdata, def_id); + + let reexport_name_doc = + ebml::get_doc(reexport_doc, + tag_items_data_item_reexport_name); + let reexport_name = ebml::doc_as_str(reexport_name_doc); + + let reexport_path; + if path == ~"" { + reexport_path = reexport_name; + } else { + reexport_path = path + ~"::" + reexport_name; + } + + // Get the item. + match maybe_find_item(def_id.node, items) { + none => {} + some(item_doc) => { + // Construct the def for this item. + let def_like = item_to_def_like(item_doc, + def_id, + cdata.cnum); + + // Hand the information off to the iteratee. + debug!("(each_path) yielding reexported \ + item: %s", reexport_path); + + let this_path_entry = + path_entry(reexport_path, def_like); + if (!f(this_path_entry)) { + broken = true; // XXX: This is awful. + } + } + } + } + } } } @@ -449,54 +502,6 @@ fn each_path(cdata: cmd, f: fn(path_entry) -> bool) { if broken { return; } - - // Next, go through all the paths. We will find items that we didn't know - // about before (reexports in particular). - // - // XXX: This is broken; the paths are actually hierarchical. - - let outer_paths = ebml::get_doc(root, tag_paths); - let inner_paths = ebml::get_doc(outer_paths, tag_paths); - - fn g(cdata: cmd, items: ebml::doc, path_doc: ebml::doc, &broken: bool, - f: fn(path_entry) -> bool) { - - if !broken { - let path = item_name(path_doc); - - // Extract the def ID. - let def_id = item_def_id(path_doc, cdata); - - // Get the item. - match maybe_find_item(def_id.node, items) { - none => { - debug!{"(each_path) ignoring implicit item: %s", - *path}; - } - some(item_doc) => { - // Construct the def for this item. - let def_like = item_to_def_like(item_doc, def_id, - cdata.cnum); - - // Hand the information off to the iteratee. - debug!{"(each_path) yielding implicit item: %s", - *path}; - let this_path_entry = path_entry(*path, def_like); - if (!f(this_path_entry)) { - broken = true; // XXX: This is awful. - } - } - } - } - } - - for ebml::tagged_docs(inner_paths, tag_paths_data_item) |path_doc| { - g(cdata, items, path_doc, broken, f); - } - - for ebml::tagged_docs(inner_paths, tag_paths_foreign_path) |path_doc| { - g(cdata, items, path_doc, broken, f); - } } fn get_item_path(cdata: cmd, id: ast::node_id) -> ast_map::path { diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index f67aa9fed7b..13ca2f5be17 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -13,6 +13,7 @@ import common::*; import middle::ty; import middle::ty::node_id_to_type; +import middle::resolve3; import syntax::ast_map; import syntax::attr; import std::serialization::serializer; @@ -44,6 +45,7 @@ tcx: ty::ctxt, reachable: hashmap, reexports: ~[(~str, def_id)], + reexports2: middle::resolve3::ExportMap2, impl_map: fn@(ast::node_id) -> ~[(ident, def_id)], item_symbols: hashmap, discrim_symbols: hashmap, @@ -57,6 +59,7 @@ enum encode_ctxt = { tcx: ty::ctxt, reachable: hashmap, reexports: ~[(~str, def_id)], + reexports2: middle::resolve3::ExportMap2, impl_map: fn@(ast::node_id) -> ~[(ident, def_id)], item_symbols: hashmap, discrim_symbols: hashmap, @@ -278,7 +281,7 @@ fn encode_trait_ref(ebml_w: ebml::writer, ecx: @encode_ctxt, t: @trait_ref) { } fn encode_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt, crate: @crate) - -> ~[entry<~str>] { + -> ~[entry<~str>] { let mut index: ~[entry<~str>] = ~[]; let mut path: ~[ident] = ~[]; ebml_w.start_tag(tag_paths); @@ -478,6 +481,31 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod, } // for encode_path(ebml_w, path, ast_map::path_mod(name)); + + // Encode the reexports of this module. + debug!("(encoding info for module) encoding reexports for %d", id); + match ecx.reexports2.find(id) { + some(exports) => { + debug!("(encoding info for module) found reexports for %d", id); + for exports.each |exp| { + debug!("(encoding info for module) reexport '%s' for %d", + exp.name, id); + ebml_w.start_tag(tag_items_data_item_reexport); + ebml_w.start_tag(tag_items_data_item_reexport_def_id); + ebml_w.wr_str(def_to_str(exp.def_id)); + ebml_w.end_tag(); + ebml_w.start_tag(tag_items_data_item_reexport_name); + ebml_w.wr_str(exp.name); + ebml_w.end_tag(); + ebml_w.end_tag(); + } + } + none => { + debug!("(encoding info for module) found no reexports for %d", + id); + } + } + ebml_w.end_tag(); } @@ -1228,6 +1256,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] { tcx: parms.tcx, reachable: parms.reachable, reexports: parms.reexports, + reexports2: parms.reexports2, impl_map: parms.impl_map, item_symbols: parms.item_symbols, discrim_symbols: parms.discrim_symbols, diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs index 7ff5d96c993..9e6afc266b8 100644 --- a/src/rustc/middle/resolve3.rs +++ b/src/rustc/middle/resolve3.rs @@ -96,6 +96,16 @@ struct binding_info { type Export = { reexp: bool, id: def_id }; type ExportMap = hashmap; +// This is the replacement export map. It maps a module to all of the exports +// within. +type ExportMap2 = hashmap; + +struct Export2 { + name: ~str; // The name of the target. + def_id: def_id; // The definition of the target. + reexport: bool; // Whether this is a reexport. +} + enum PatternBindingMode { RefutableMode, IrrefutableMode @@ -701,6 +711,7 @@ struct Resolver { let def_map: DefMap; let impl_map: ImplMap; let export_map: ExportMap; + let export_map2: ExportMap2; let trait_map: TraitMap; new(session: session, lang_items: LanguageItems, crate: @crate) { @@ -741,6 +752,7 @@ struct Resolver { self.def_map = int_hash(); self.impl_map = int_hash(); self.export_map = int_hash(); + self.export_map2 = int_hash(); self.trait_map = @int_hash(); } @@ -2734,6 +2746,7 @@ fn record_exports_for_module_subtree(module_: @Module) { } fn record_exports_for_module(module_: @Module) { + let mut exports2 = ~[]; for module_.exported_names.each |name, node_id| { let mut exports = ~[]; for self.namespaces.each |namespace| { @@ -2752,22 +2765,49 @@ fn record_exports_for_module(module_: @Module) { // Nothing to do. } ChildNameDefinition(target_def) => { + debug!("(computing exports) found child export '%s' \ + for %?", + *self.atom_table.atom_to_str(name), + module_.def_id); vec::push(exports, { reexp: false, id: def_id_of_def(target_def) }); + vec::push(exports2, Export2 { + reexport: false, + name: copy *self.atom_table.atom_to_str(name), + def_id: def_id_of_def(target_def) + }); } ImportNameDefinition(target_def) => { + debug!("(computing exports) found reexport '%s' for \ + %?", + *self.atom_table.atom_to_str(name), + module_.def_id); vec::push(exports, { reexp: true, id: def_id_of_def(target_def) }); + vec::push(exports2, Export2 { + reexport: true, + name: copy *self.atom_table.atom_to_str(name), + def_id: def_id_of_def(target_def) + }); } } } self.export_map.insert(node_id, exports); } + + match copy module_.def_id { + some(def_id) => { + self.export_map2.insert(def_id.node, move exports2); + debug!("(computing exports) writing exports for %d (some)", + def_id.node); + } + none => {} + } } // Implementation scope creation @@ -4846,6 +4886,7 @@ fn dump_impl_scopes(impl_scopes: ImplScopes) { fn resolve_crate(session: session, lang_items: LanguageItems, crate: @crate) -> { def_map: DefMap, exp_map: ExportMap, + exp_map2: ExportMap2, impl_map: ImplMap, trait_map: TraitMap } { @@ -4854,6 +4895,7 @@ fn resolve_crate(session: session, lang_items: LanguageItems, crate: @crate) return { def_map: resolver.def_map, exp_map: resolver.export_map, + exp_map2: resolver.export_map2, impl_map: resolver.impl_map, trait_map: resolver.trait_map }; diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index d1452fa4906..6e1f2e79805 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -5648,6 +5648,7 @@ fn crate_ctxt_to_encode_parms(cx: @crate_ctxt) tcx: cx.tcx, reachable: cx.reachable, reexports: reexports(cx), + reexports2: cx.exp_map2, impl_map: |a| impl_map(cx, a), item_symbols: cx.item_symbols, discrim_symbols: cx.discrim_symbols, @@ -5662,9 +5663,10 @@ fn reexports(cx: @crate_ctxt) -> ~[(~str, ast::def_id)] { for defs.each |def| { if !def.reexp { again; } let path = match check cx.tcx.items.get(exp_id) { - ast_map::node_export(_, path) => { - ast_map::path_to_str(*path) - } + ast_map::node_export(_, path) => { + + ast_map::path_to_str(*path) + } }; vec::push(reexports, (path, def.id)); } @@ -5711,10 +5713,15 @@ fn write_abi_version(ccx: @crate_ctxt) { false); } -fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt, - output: ~str, emap: resolve3::ExportMap, +fn trans_crate(sess: session::session, + crate: @ast::crate, + tcx: ty::ctxt, + output: ~str, + emap: resolve3::ExportMap, + emap2: resolve3::ExportMap2, maps: astencode::maps) - -> (ModuleRef, link_meta) { + -> (ModuleRef, link_meta) { + let symbol_hasher = @hash::default_state(); let link_meta = link::build_link_meta(sess, *crate, output, symbol_hasher); @@ -5773,6 +5780,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt, intrinsics: intrinsics, item_vals: int_hash::(), exp_map: emap, + exp_map2: emap2, reachable: reachable, item_symbols: int_hash::<~str>(), mut main_fn: none::, diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 8e10be8e211..7930b596217 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -88,6 +88,7 @@ struct BuilderRef_res { intrinsics: hashmap<~str, ValueRef>, item_vals: hashmap, exp_map: resolve3::ExportMap, + exp_map2: resolve3::ExportMap2, reachable: reachable::map, item_symbols: hashmap, mut main_fn: option,