]> git.lizzy.rs Git - rust.git/commitdiff
rustc: Always resolve reexported names from original def
authorHaitao Li <lihaitao@gmail.com>
Fri, 20 Jan 2012 18:45:25 +0000 (02:45 +0800)
committerHaitao Li <lihaitao@gmail.com>
Sat, 21 Jan 2012 10:03:09 +0000 (18:03 +0800)
Issue #1501

src/comp/metadata/csearch.rs
src/comp/metadata/cstore.rs
src/comp/metadata/decoder.rs
src/comp/middle/resolve.rs

index 123f375cf2abc77081729bdf2d7e58c592a8d55c..7968b74457bc035a4cc0cf9f4802064513523e69 100644 (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_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;
index 44076ab60b89fc28fabadb081916a0edd8f9a0ab..3c75df586befa959594c566165665b46c0ca3919 100644 (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 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
 // 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 lteq(a: crate_hash, b: crate_hash) -> bool {
     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;
index 6b573de4c50a49573e9a771ef58dc17c4e2b2eb1..9855fa75d42ca85d55ea593526d5c5643fefa355 100644 (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_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) {
index 34fb2a86630be180bbb891d132c5e10f0649fbb9..6f0ae757049c959429cbde65f024e2d08c95f4a7 100644 (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>;