]> git.lizzy.rs Git - rust.git/commitdiff
rustc: Implement non-renamed re-export across crates
authorHaitao Li <lihaitao@gmail.com>
Thu, 15 Dec 2011 10:42:27 +0000 (18:42 +0800)
committerHaitao Li <lihaitao@gmail.com>
Fri, 16 Dec 2011 09:16:00 +0000 (17:16 +0800)
First patch for issue #1115. Not yet ready for re-exported modules which
are renamed when importing them.

src/comp/driver/rustc.rs
src/comp/metadata/csearch.rs
src/comp/metadata/decoder.rs
src/comp/metadata/encoder.rs
src/comp/middle/resolve.rs
src/comp/middle/trans.rs
src/comp/middle/trans_common.rs

index 97a912c4d9cb480f6a14c0a215e911e89410d427..b2c8380e130b134e3c7739c3c2865b1e8e98b98e 100644 (file)
@@ -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 ann_identified_post(node: pprust::ann_node) {
       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);
index 48b9774db51950204c350fa6c8fedb447c563b68..222d6ac7f0e0f6d0371cceabbe4171e271b4f0f9 100644 (file)
@@ -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] {
index d5d981bb81c4badfe16ae6121914390f451a28f8..b4b9712b807e706ab8ce7ae5fb9a91aafb258190 100644 (file)
@@ -15,7 +15,8 @@
 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 eq_item(data: [u8], s: str) -> bool {
     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);
index 150c241ff60360a459e04ff4ce6139065f263b0d..c013ec614edf75a2734e16d09d243adb6cd1ac3a 100644 (file)
@@ -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<str>] {
+fn encode_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt, crate: @crate)
+    -> [entry<str>] {
     let index: [entry<str>] = [];
     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<str>]) {
+    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);
index 55ff537d447af057e8a061e16ff24e5b1545fa3c..73a12b56907852afa9de05e914e11af743ae5e73 100644 (file)
 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 @@ fn eq(v1: key, v2: key) -> bool {
 
 type def_map = hashmap<node_id, def>;
 type ext_map = hashmap<def_id, [ident]>;
+type exp_map = hashmap<str, def>;
 
 type env =
     {cstore: cstore::cstore,
      def_map: def_map,
      ast_map: ast_map::map,
      imports: hashmap<ast::node_id, import_state>,
+     exp_map: exp_map,
      mod_map: hashmap<ast::node_id, @indexed_mod>,
      block_map: hashmap<ast::node_id, [glob_imp_def]>,
-     ext_map: hashmap<def_id, [ident]>,
+     ext_map: ext_map,
      ext_cache: ext_hash,
      used_imports: {mutable track: bool,
                     mutable data: [ast::node_id]},
@@ -121,12 +124,13 @@ fn eq(v1: key, v2: key) -> bool {
 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<T>(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<def>) {
+        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 lookup_glob_any(e: env, info: @indexed_mod, sp: span, ident: ident) ->
                 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);
                     }
                   }
                   _ { }
index e9f769b4ec5d8e4341fc8d4aae4603e5f8d8001c..79dc94483161d1b14d38cae7c5c9f3dccfddb2f9 100644 (file)
@@ -20,7 +20,7 @@
 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::<ValueRef>(),
           ast_map: amap,
+          exp_map: emap,
           item_symbols: new_int_hash::<str>(),
           mutable main_fn: none::<ValueRef>,
           link_meta: link_meta,
index 889ba2e44a12f1e79fa8ace08473f3484aeaf94e..7d9775a6c2a95056bd6396fc5db9aa3db4cd775a 100644 (file)
@@ -84,6 +84,7 @@
      intrinsics: hashmap<str, ValueRef>,
      item_ids: hashmap<ast::node_id, ValueRef>,
      ast_map: ast_map::map,
+     exp_map: hashmap<str, ast::def>,
      item_symbols: hashmap<ast::node_id, str>,
      mutable main_fn: option::t<ValueRef>,
      link_meta: link::link_meta,