From 14fcb135a99c4eb02376f51dd51a75e4a5b31307 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Fri, 16 Dec 2011 09:42:48 +0100 Subject: [PATCH] Improve resolution of impls Issue #1227 --- src/comp/middle/resolve.rs | 51 ++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 19d74e11cd8..bc095e992f0 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -2,7 +2,7 @@ import syntax::{ast, ast_util, codemap}; import syntax::ast::*; import ast::{ident, fn_ident, def, def_id, node_id}; -import syntax::ast_util::{local_def, def_id_of_def}; +import syntax::ast_util::{local_def, def_id_of_def, is_exported}; import metadata::{csearch, cstore}; import driver::session::session; @@ -494,7 +494,8 @@ fn resolve_import(e: env, defid: ast::def_id, name: ast::ident, impls: [@ast::item]) { let val = lookup(ns_value), typ = lookup(ns_type), md = lookup(ns_module); - if is_none(val) && is_none(typ) && is_none(md) { + if is_none(val) && is_none(typ) && is_none(md) && + vec::len(impls) == 0u { unresolved_err(e, cx, sp, name, "import"); } else { e.imports.insert(id, resolved(val, typ, md, @impls, name, sp)); @@ -1112,7 +1113,7 @@ fn lookup_in_local_native_mod(e: env, node_id: node_id, sp: span, id: ident, fn lookup_in_local_mod(e: env, node_id: node_id, sp: span, id: ident, ns: namespace, dr: dir) -> option::t { let info = e.mod_map.get(node_id); - if dr == outside && !ast_util::is_exported(id, option::get(info.m)) { + if dr == outside && !is_exported(id, option::get(info.m)) { // if we're in a native mod, then dr==inside, so info.m is some _mod ret none::; // name is not visible } @@ -1637,12 +1638,22 @@ fn resolve_impls(e: @env, c: @ast::crate) { } fn find_impls_in_view_item(e: env, vi: @ast::view_item, - &impls: [@ast::item]) { + &impls: [@ast::item], sc: iscopes) { alt vi.node { - ast::view_item_import(ident, _, id) { - // FIXME if single name, simply look in our own iscope - alt e.imports.get(id) { - resolved(_, _, _, is, _, _) { impls += *is; } + ast::view_item_import(_, 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 += [imp]; } + } + if vec::len(found) > 0u { impls += found; } + } + } else { + alt e.imports.get(id) { + resolved(_, _, _, is, _, _) { impls += *is; } + } } } ast::view_item_import_from(base, names, _) { @@ -1667,11 +1678,12 @@ fn find_impls_in_view_item(e: env, vi: @ast::view_item, } fn find_impls_in_item(i: @ast::item, &impls: [@ast::item], - name: option::t, _dir: dir) { - // FIXME check exports + name: option::t, + ck_exports: option::t) { alt i.node { ast::item_impl(_, _, _) { - if alt name { some(n) { n == i.ident } _ { true } } { + if alt name { some(n) { n == i.ident } _ { true } } && + alt ck_exports { some(m) { is_exported(i.ident, m) } _ { true } } { impls += [i]; } } @@ -1679,14 +1691,15 @@ fn find_impls_in_item(i: @ast::item, &impls: [@ast::item], } } +// FIXME[impl] external importing of impls fn find_impls_in_mod(e: env, m: def, &impls: [@ast::item], name: option::t) { alt m { ast::def_mod(defid) { - // FIXME external importing of impls if defid.crate == ast::local_crate { - for i in option::get(e.mod_map.get(defid.node).m).items { - find_impls_in_item(i, impls, name, outside); + let md = option::get(e.mod_map.get(defid.node).m); + for i in md.items { + find_impls_in_item(i, impls, name, some(md)); } } } @@ -1699,11 +1712,13 @@ type iscopes = list<@[@ast::item]>; fn visit_block_with_impl_scope(e: @env, b: ast::blk, sc: iscopes, v: vt) { let impls = []; - for vi in b.node.view_items { find_impls_in_view_item(*e, vi, impls); } + for vi in b.node.view_items { + find_impls_in_view_item(*e, vi, impls, sc); + } for st in b.node.stmts { alt st.node { ast::stmt_decl(@{node: ast::decl_item(i), _}, _) { - find_impls_in_item(i, impls, none, inside); + find_impls_in_item(i, impls, none, none); } _ {} } @@ -1715,8 +1730,8 @@ fn visit_block_with_impl_scope(e: @env, b: ast::blk, sc: iscopes, fn visit_mod_with_impl_scope(e: @env, m: ast::_mod, s: span, sc: iscopes, v: vt) { let impls = []; - for vi in m.view_items { find_impls_in_view_item(*e, vi, impls); } - for i in m.items { find_impls_in_item(i, impls, none, inside); } + for vi in m.view_items { find_impls_in_view_item(*e, vi, impls, sc); } + for i in m.items { find_impls_in_item(i, impls, none, none); } visit::visit_mod(m, s, vec::len(impls) > 0u ? cons(@impls, @sc) : sc, v); }