about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-01-26 17:33:12 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-01-26 18:58:35 +0100
commitc590bdeea41f5476f42c6a7cb067e162328bdbc2 (patch)
treec728974e1ceab0b3598b47e97811cf6201840322
parent6bead0e4ccfa65a89bee8db6d4587e297fba1a57 (diff)
downloadrust-c590bdeea41f5476f42c6a7cb067e162328bdbc2.tar.gz
rust-c590bdeea41f5476f42c6a7cb067e162328bdbc2.zip
Make re-exporting of impls work
Closes #1438
-rw-r--r--src/comp/driver/driver.rs2
-rw-r--r--src/comp/metadata/encoder.rs34
-rw-r--r--src/comp/middle/resolve.rs181
-rw-r--r--src/comp/middle/trans.rs5
-rw-r--r--src/comp/middle/trans_common.rs1
-rw-r--r--src/comp/syntax/visit.rs23
6 files changed, 135 insertions, 111 deletions
diff --git a/src/comp/driver/driver.rs b/src/comp/driver/driver.rs
index 41130766035..87b00a9e25b 100644
--- a/src/comp/driver/driver.rs
+++ b/src/comp/driver/driver.rs
@@ -199,7 +199,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
         time(time_passes, "translation",
              bind trans::trans_crate(sess, crate, ty_cx,
                                      outputs.obj_filename, exp_map, ast_map,
-                                     mut_map, copy_map, last_uses,
+                                     mut_map, copy_map, last_uses, impl_map,
                                      method_map, dict_map));
     time(time_passes, "LLVM passes",
          bind link::write::run_passes(sess, llmod, outputs.obj_filename));
diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs
index 31db8561dec..a3bc668ad9d 100644
--- a/src/comp/metadata/encoder.rs
+++ b/src/comp/metadata/encoder.rs
@@ -1,6 +1,6 @@
 // Metadata encoding
 
-import std::{io, ebml, map};
+import std::{io, ebml, map, list};
 import io::writer_util;
 import syntax::ast::*;
 import syntax::ast_util;
@@ -151,13 +151,14 @@ fn encode_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt, crate: @crate)
 
 fn encode_reexport_paths(ebml_w: ebml::writer,
                          ecx: @encode_ctxt, &index: [entry<str>]) {
-    ecx.ccx.exp_map.items {|key, def|
-        let path = key.path;
-        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);
+    ecx.ccx.exp_map.items {|path, defs|
+        for def in *defs {
+            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);
+        }
     }
 }
 
@@ -258,23 +259,22 @@ fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::writer,
     }
 }
 
-fn encode_info_for_mod(ebml_w: ebml::writer, md: _mod,
+fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
                        id: node_id, name: ident) {
     ebml::start_tag(ebml_w, tag_items_data_item);
     encode_def_id(ebml_w, local_def(id));
     encode_family(ebml_w, 'm' as u8);
     encode_name(ebml_w, name);
-    for i in md.items {
-        alt i.node {
-          item_impl(_, _, _, _) {
+    alt ecx.ccx.impl_map.get(id) {
+      list::cons(impls, @list::nil) {
+        for i in *impls {
             if ast_util::is_exported(i.ident, md) {
                 ebml::start_tag(ebml_w, tag_mod_impl);
-                ebml_w.writer.write(str::bytes(def_to_str(local_def(i.id))));
+                ebml_w.writer.write(str::bytes(def_to_str(i.did)));
                 ebml::end_tag(ebml_w);
             }
-          }
-          _ {}
         }
+      }
     }
     ebml::end_tag(ebml_w);
 }
@@ -306,7 +306,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         ebml::end_tag(ebml_w);
       }
       item_mod(m) {
-        encode_info_for_mod(ebml_w, m, item.id, item.ident);
+        encode_info_for_mod(ecx, ebml_w, m, item.id, item.ident);
       }
       item_native_mod(_) {
         ebml::start_tag(ebml_w, tag_items_data_item);
@@ -447,7 +447,7 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
     let index: [entry<int>] = [];
     ebml::start_tag(ebml_w, tag_items_data);
     index += [{val: crate_node_id, pos: ebml_w.writer.tell()}];
-    encode_info_for_mod(ebml_w, crate_mod, crate_node_id, "");
+    encode_info_for_mod(ecx, ebml_w, crate_mod, crate_node_id, "");
     ecx.ccx.ast_map.items {|key, val|
         alt val {
           middle::ast_map::node_item(i) {
diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs
index 0548026c0c5..f6fe2a79e4b 100644
--- a/src/comp/middle/resolve.rs
+++ b/src/comp/middle/resolve.rs
@@ -82,22 +82,6 @@ fn new_ext_hash() -> ext_hash {
     ret std::map::mk_hashmap::<key, def>(hash, eq);
 }
 
-fn new_exp_hash() -> exp_map {
-    type key = {path: str, ns: namespace};
-    fn hash(v: key) -> uint {
-        ret str::hash(v.path) +
-                alt v.ns {
-                  ns_val(_) { 1u }
-                  ns_type { 2u }
-                  ns_module { 3u }
-                };
-    }
-    fn eq(v1: key, v2: key) -> bool {
-        ret str::eq(v1.path, v2.path) && v1.ns == v2.ns;
-    }
-    ret std::map::mk_hashmap::<key, def>(hash, eq);
-}
-
 enum mod_index_entry {
     mie_view_item(@ast::view_item),
     mie_import_ident(node_id, codemap::span),
@@ -125,9 +109,9 @@ type indexed_mod = {
 
 type def_map = hashmap<node_id, def>;
 type ext_map = hashmap<def_id, [ident]>;
-type exp_map = hashmap<{path: str, ns: namespace}, def>;
+type exp_map = hashmap<str, @mutable [def]>;
 type impl_map = hashmap<node_id, iscopes>;
-type impl_cache = hashmap<def_id, @[@_impl]>;
+type impl_cache = hashmap<def_id, option::t<@[@_impl]>>;
 
 type env =
     {cstore: cstore::cstore,
@@ -168,7 +152,7 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
           def_map: new_int_hash(),
           ast_map: amap,
           imports: new_int_hash(),
-          exp_map: new_exp_hash(),
+          exp_map: new_str_hash(),
           mod_map: new_int_hash(),
           block_map: new_int_hash(),
           ext_map: new_def_hash(),
@@ -1725,31 +1709,40 @@ fn check_exports(e: @env) {
         let (m, v, t) = (lookup(ns_module),
                          lookup(ns_val(ns_any_value)),
                          lookup(ns_type));
-        maybe_add_reexport(e, path + ident, ns_module, m);
-        maybe_add_reexport(e, path + ident, ns_val(ns_any_value), v);
-        maybe_add_reexport(e, path + ident, ns_type, t);
-        ret is_some(m) || is_some(v) || is_some(t);
-    }
-
-    fn maybe_add_reexport(e: @env, path: str, ns: namespace,
-                          def: option::t<def>) {
-        if option::is_some(def) {
-            e.exp_map.insert({path: path, ns: ns}, option::get(def));
+        let full_path = path + ident;
+        maybe_add_reexport(e, full_path, m);
+        maybe_add_reexport(e, full_path, v);
+        maybe_add_reexport(e, full_path, t);
+        is_some(m) || is_some(v) || is_some(t)
+    }
+
+    fn maybe_add_reexport(e: @env, path: str, def: option::t<def>) {
+        alt def {
+          some(def) {
+            alt e.exp_map.find(path) {
+              some(v) { *v += [def]; }
+              none { e.exp_map.insert(path, @mutable [def]); }
+            }
+          }
+          _ {}
         }
     }
 
-    fn check_export(e: @env, ident: str, val: @indexed_mod, vi: @view_item) {
+    fn check_export(e: @env, ident: str, val: @indexed_mod,
+                    vi: @view_item) {
+        let found_something = false;
+        let full_path = val.path + ident;
         if val.index.contains_key(ident) {
+            found_something = true;
             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,
-                                           ns_val(ns_any_value), v);
-                        maybe_add_reexport(e, val.path + rid, ns_type, t);
-                        maybe_add_reexport(e, val.path + rid, ns_module, m);
+                        maybe_add_reexport(e, full_path, v);
+                        maybe_add_reexport(e, full_path, t);
+                        maybe_add_reexport(e, full_path, m);
                       }
                       _ { }
                     }
@@ -1757,9 +1750,9 @@ fn check_exports(e: @env) {
                   _ { }
                 }
             }
-        } else if lookup_glob_any(e, val, vi.span, val.path, ident) {
-            // do nothing
-        } else {
+        }
+        found_something |= lookup_glob_any(e, val, vi.span, val.path, ident);
+        if !found_something {
             e.sess.span_warn(vi.span,
                              #fmt("exported item %s is not defined", ident));
         }
@@ -1849,40 +1842,52 @@ type iscopes = list<@[@_impl]>;
 fn resolve_impls(e: @env, c: @ast::crate) {
     visit::visit_crate(*c, nil, visit::mk_vt(@{
         visit_block: bind visit_block_with_impl_scope(e, _, _, _),
-        visit_mod: bind visit_mod_with_impl_scope(e, _, _, _, _),
+        visit_mod: bind visit_mod_with_impl_scope(e, _, _, _, _, _),
         visit_expr: bind resolve_impl_in_expr(e, _, _, _)
         with *visit::default_visitor()
     }));
 }
 
 fn find_impls_in_view_item(e: env, vi: @ast::view_item,
-                           &impls: [@_impl], sc: iscopes) {
+                           &impls: [@_impl], sc: option::t<iscopes>) {
+    fn lookup_imported_impls(e: env, id: ast::node_id,
+                             act: fn(@[@_impl])) {
+        alt e.imports.get(id) {
+          resolved(_, _, _, is, _, _) { act(is); }
+          todo(node_id, name, path, span, scopes) {
+            resolve_import(e, local_def(node_id), name, *path, span,
+                           scopes);
+            alt e.imports.get(id) {
+              resolved(_, _, _, is, _, _) { act(is); }
+            }
+          }
+          _ {}
+        }
+    }
     alt vi.node {
       ast::view_item_import(name, pt, id) {
         let found = [];
         if vec::len(*pt) == 1u {
-            list::iter(sc) {|level|
-                if vec::len(found) > 0u { ret; }
-                for imp in *level {
-                    if imp.ident == pt[0] {
-                        found += [@{ident: name with *imp}];
+            option::may(sc) {|sc|
+                list::iter(sc) {|level|
+                    if vec::len(found) > 0u { ret; }
+                    for imp in *level {
+                        if imp.ident == pt[0] {
+                            found += [@{ident: name with *imp}];
+                        }
                     }
+                    if vec::len(found) > 0u { impls += found; }
                 }
-                if vec::len(found) > 0u { impls += found; }
             }
         } else {
-            alt e.imports.get(id) {
-              resolved(_, _, _, is, _, _) {
+            lookup_imported_impls(e, id) {|is|
                 for i in *is { impls += [@{ident: name with *i}]; }
-              }
             }
         }
       }
       ast::view_item_import_from(base, names, _) {
         for nm in names {
-            alt e.imports.get(nm.node.id) {
-              resolved(_, _, _, is, _, _) { impls += *is; }
-            }
+            lookup_imported_impls(e, nm.node.id) {|is| impls += *is; }
         }
       }
       ast::view_item_import_glob(ids, id) {
@@ -1922,34 +1927,45 @@ fn find_impls_in_item(e: env, i: @ast::item, &impls: [@_impl],
     }
 }
 
+fn find_impls_in_mod_by_id(e: env, defid: def_id, &impls: [@_impl],
+                           name: option::t<ident>) {
+    let cached;
+    alt e.impl_cache.find(defid) {
+      some(some(v)) { cached = v; }
+      some(none) { ret; }
+      none {
+        e.impl_cache.insert(defid, none);
+        cached = if defid.crate == ast::local_crate {
+            let tmp = [];
+            let md = option::get(e.mod_map.get(defid.node).m);
+            for vi in md.view_items {
+                find_impls_in_view_item(e, vi, tmp, none);
+            }
+            for i in md.items {
+                find_impls_in_item(e, i, tmp, none, none);
+            }
+            @vec::filter(tmp) {|i| is_exported(e, i.ident, md)}
+        } else {
+            csearch::get_impls_for_mod(e.sess.cstore, defid, none)
+        };
+        e.impl_cache.insert(defid, some(cached));
+      }
+    }
+    alt name {
+      some(n) {
+        for im in *cached {
+            if n == im.ident { impls += [im]; }
+        }
+      }
+      _ { impls += *cached; }
+    }
+}
+
 fn find_impls_in_mod(e: env, m: def, &impls: [@_impl],
                      name: option::t<ident>) {
     alt m {
       ast::def_mod(defid) {
-        let cached;
-        alt e.impl_cache.find(defid) {
-          some(v) { cached = v; }
-          none {
-            cached = if defid.crate == ast::local_crate {
-                let tmp = [];
-                for i in option::get(e.mod_map.get(defid.node).m).items {
-                    find_impls_in_item(e, i, tmp, none, none);
-                }
-                @tmp
-            } else {
-                csearch::get_impls_for_mod(e.sess.cstore, defid, none)
-            };
-            e.impl_cache.insert(defid, cached);
-          }
-        }
-        alt name {
-          some(n) {
-            for im in *cached {
-                if n == im.ident { impls += [im]; }
-            }
-          }
-          _ { impls += *cached; }
-        }
+        find_impls_in_mod_by_id(e, defid, impls, name);
       }
       _ {}
     }
@@ -1959,7 +1975,7 @@ fn visit_block_with_impl_scope(e: @env, b: ast::blk, sc: iscopes,
                                v: vt<iscopes>) {
     let impls = [];
     for vi in b.node.view_items {
-        find_impls_in_view_item(*e, vi, impls, sc);
+        find_impls_in_view_item(*e, vi, impls, some(sc));
     }
     for st in b.node.stmts {
         alt st.node {
@@ -1973,12 +1989,17 @@ fn visit_block_with_impl_scope(e: @env, b: ast::blk, sc: iscopes,
     visit::visit_block(b, sc, v);
 }
 
-fn visit_mod_with_impl_scope(e: @env, m: ast::_mod, s: span, sc: iscopes,
-                             v: vt<iscopes>) {
+fn visit_mod_with_impl_scope(e: @env, m: ast::_mod, s: span, id: node_id,
+                             sc: iscopes, v: vt<iscopes>) {
     let impls = [];
-    for vi in m.view_items { find_impls_in_view_item(*e, vi, impls, sc); }
+    for vi in m.view_items {
+        find_impls_in_view_item(*e, vi, impls, some(sc));
+    }
     for i in m.items { find_impls_in_item(*e, i, impls, none, none); }
-    visit::visit_mod(m, s, vec::len(impls) > 0u ? cons(@impls, @sc) : sc, v);
+    let impls = @impls;
+    visit::visit_mod(m, s, id,
+                     vec::len(*impls) > 0u ? cons(impls, @sc) : sc, v);
+    e.impl_map.insert(id, cons(impls, @nil));
 }
 
 fn resolve_impl_in_expr(e: @env, x: @ast::expr, sc: iscopes, v: vt<iscopes>) {
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 1feddbdb54c..9e978b3572a 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -5498,8 +5498,8 @@ fn write_abi_version(ccx: @crate_ctxt) {
 fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
                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, method_map: typeck::method_map,
-               dict_map: typeck::dict_map)
+               last_uses: last_use::last_uses, impl_map: resolve::impl_map,
+               method_map: typeck::method_map, dict_map: typeck::dict_map)
     -> (ModuleRef, link::link_meta) {
     let sha = std::sha1::mk_sha1();
     let link_meta = link::build_link_meta(sess, *crate, output, sha);
@@ -5576,6 +5576,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
           mut_map: mut_map,
           copy_map: copy_map,
           last_uses: last_uses,
+          impl_map: impl_map,
           method_map: method_map,
           dict_map: dict_map,
           stats:
diff --git a/src/comp/middle/trans_common.rs b/src/comp/middle/trans_common.rs
index 8829c2b756e..790f78aed58 100644
--- a/src/comp/middle/trans_common.rs
+++ b/src/comp/middle/trans_common.rs
@@ -108,6 +108,7 @@ type crate_ctxt =
      mut_map: mut::mut_map,
      copy_map: alias::copy_map,
      last_uses: last_use::last_uses,
+     impl_map: resolve::impl_map,
      method_map: typeck::method_map,
      dict_map: typeck::dict_map,
      stats: stats,
diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs
index e60e5b097ea..ba995192859 100644
--- a/src/comp/syntax/visit.rs
+++ b/src/comp/syntax/visit.rs
@@ -40,7 +40,7 @@ fn tps_of_fn(fk: fn_kind) -> [ty_param] {
 type visitor<E> =
     // takes the components so that one function can be
     // generic over constr and ty_constr
-    @{visit_mod: fn@(_mod, span, E, vt<E>),
+    @{visit_mod: fn@(_mod, span, node_id, E, vt<E>),
       visit_view_item: fn@(@view_item, E, vt<E>),
       visit_native_item: fn@(@native_item, E, vt<E>),
       visit_item: fn@(@item, E, vt<E>),
@@ -57,7 +57,7 @@ type visitor<E> =
       visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>)};
 
 fn default_visitor<E>() -> visitor<E> {
-    ret @{visit_mod: bind visit_mod::<E>(_, _, _, _),
+    ret @{visit_mod: bind visit_mod::<E>(_, _, _, _, _),
           visit_view_item: bind visit_view_item::<E>(_, _, _),
           visit_native_item: bind visit_native_item::<E>(_, _, _),
           visit_item: bind visit_item::<E>(_, _, _),
@@ -75,7 +75,7 @@ fn default_visitor<E>() -> visitor<E> {
 }
 
 fn visit_crate<E>(c: crate, e: E, v: vt<E>) {
-    v.visit_mod(c.node.module, c.span, e, v);
+    v.visit_mod(c.node.module, c.span, crate_node_id, e, v);
 }
 
 fn visit_crate_directive<E>(cd: @crate_directive, e: E, v: vt<E>) {
@@ -91,7 +91,7 @@ fn visit_crate_directive<E>(cd: @crate_directive, e: E, v: vt<E>) {
     }
 }
 
-fn visit_mod<E>(m: _mod, _sp: span, e: E, v: vt<E>) {
+fn visit_mod<E>(m: _mod, _sp: span, _id: node_id, e: E, v: vt<E>) {
     for vi: @view_item in m.view_items { v.visit_view_item(vi, e, v); }
     for i: @item in m.items { v.visit_item(i, e, v); }
 }
@@ -110,7 +110,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
       item_fn(decl, tp, body) {
         v.visit_fn(fk_item_fn(i.ident, tp), decl, body, i.span, i.id, e, v);
       }
-      item_mod(m) { v.visit_mod(m, i.span, e, v); }
+      item_mod(m) { v.visit_mod(m, i.span, i.id, e, v); }
       item_native_mod(nm) {
         for vi: @view_item in nm.view_items { v.visit_view_item(vi, e, v); }
         for ni: @native_item in nm.items { v.visit_native_item(ni, e, v); }
@@ -376,7 +376,7 @@ fn visit_arm<E>(a: arm, e: E, v: vt<E>) {
 type simple_visitor =
     // takes the components so that one function can be
     // generic over constr and ty_constr
-    @{visit_mod: fn@(_mod, span),
+    @{visit_mod: fn@(_mod, span, node_id),
       visit_view_item: fn@(@view_item),
       visit_native_item: fn@(@native_item),
       visit_item: fn@(@item),
@@ -395,7 +395,7 @@ type simple_visitor =
 fn simple_ignore_ty(_t: @ty) {}
 
 fn default_simple_visitor() -> simple_visitor {
-    ret @{visit_mod: fn@(_m: _mod, _sp: span) { },
+    ret @{visit_mod: fn@(_m: _mod, _sp: span, _id: node_id) { },
           visit_view_item: fn@(_vi: @view_item) { },
           visit_native_item: fn@(_ni: @native_item) { },
           visit_item: fn@(_i: @item) { },
@@ -415,9 +415,10 @@ fn default_simple_visitor() -> simple_visitor {
 }
 
 fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
-    fn v_mod(f: fn@(_mod, span), m: _mod, sp: span, &&e: (), v: vt<()>) {
-        f(m, sp);
-        visit_mod(m, sp, e, v);
+    fn v_mod(f: fn@(_mod, span, node_id), m: _mod, sp: span, id: node_id,
+             &&e: (), v: vt<()>) {
+        f(m, sp, id);
+        visit_mod(m, sp, id, e, v);
     }
     fn v_view_item(f: fn@(@view_item), vi: @view_item, &&e: (), v: vt<()>) {
         f(vi);
@@ -484,7 +485,7 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
     } else {
         bind v_ty(v.visit_ty, _, _, _)
     };
-    ret mk_vt(@{visit_mod: bind v_mod(v.visit_mod, _, _, _, _),
+    ret mk_vt(@{visit_mod: bind v_mod(v.visit_mod, _, _, _, _, _),
                 visit_view_item: bind v_view_item(v.visit_view_item, _, _, _),
                 visit_native_item:
                     bind v_native_item(v.visit_native_item, _, _, _),