diff options
| author | Marijn Haverbeke <marijnh@gmail.com> | 2012-01-26 17:33:12 +0100 |
|---|---|---|
| committer | Marijn Haverbeke <marijnh@gmail.com> | 2012-01-26 18:58:35 +0100 |
| commit | c590bdeea41f5476f42c6a7cb067e162328bdbc2 (patch) | |
| tree | c728974e1ceab0b3598b47e97811cf6201840322 | |
| parent | 6bead0e4ccfa65a89bee8db6d4587e297fba1a57 (diff) | |
| download | rust-c590bdeea41f5476f42c6a7cb067e162328bdbc2.tar.gz rust-c590bdeea41f5476f42c6a7cb067e162328bdbc2.zip | |
Make re-exporting of impls work
Closes #1438
| -rw-r--r-- | src/comp/driver/driver.rs | 2 | ||||
| -rw-r--r-- | src/comp/metadata/encoder.rs | 34 | ||||
| -rw-r--r-- | src/comp/middle/resolve.rs | 181 | ||||
| -rw-r--r-- | src/comp/middle/trans.rs | 5 | ||||
| -rw-r--r-- | src/comp/middle/trans_common.rs | 1 | ||||
| -rw-r--r-- | src/comp/syntax/visit.rs | 23 |
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, _, _, _), |
