diff options
| author | Tim Chevalier <chevalier@alum.wellesley.edu> | 2012-07-16 19:14:55 -0700 |
|---|---|---|
| committer | Tim Chevalier <chevalier@alum.wellesley.edu> | 2012-07-17 12:40:58 -0700 |
| commit | cf9a9d1ae8ed74a69b529f526eed1462813817cd (patch) | |
| tree | e2422f7e1b53e18461875b83875c4bcc7f41d95b | |
| parent | bc87e66355e658cffb84396d1783364e23ddc6d2 (diff) | |
| download | rust-cf9a9d1ae8ed74a69b529f526eed1462813817cd.tar.gz rust-cf9a9d1ae8ed74a69b529f526eed1462813817cd.zip | |
Remove most of old resolve
resolve has a few type definitions in it that are used, so I left those and deleted everything else. Also, I switched rustdoc to use resolve3 instead of the old resolve. In a future commit I'll remove the type definitions entirely, as they're just duplicates of types defined in resolve3.
| -rw-r--r-- | src/rustc/middle/liveness.rs | 2 | ||||
| -rw-r--r-- | src/rustc/middle/resolve.rs | 2333 | ||||
| -rw-r--r-- | src/rustc/middle/trans/alt.rs | 2 | ||||
| -rw-r--r-- | src/rustdoc/astsrv.rs | 3 | ||||
| -rw-r--r-- | src/rustdoc/reexport_pass.rs | 7 |
5 files changed, 11 insertions, 2336 deletions
diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index 02d24772c25..251b0368910 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -360,7 +360,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, visit::visit_fn(fk, decl, body, sp, id, fn_maps, v); alt fk { - visit::fk_ctor(_, _, _, class_did) { + visit::fk_ctor(_, _, _, _, class_did) { add_class_fields(fn_maps, class_did); } _ {} diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index a4c85bee55e..a7ffc9cd26d 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -31,82 +31,6 @@ export _impl, iscopes, method_info; // locates all names (in expressions, types, and alt patterns) and resolves // them, storing the resulting def in the AST nodes. -enum scope { - scope_toplevel, - scope_crate, - scope_item(@ast::item), - scope_bare_fn(ast::fn_decl, node_id, ~[ast::ty_param]), - scope_fn_expr(ast::fn_decl, node_id, ~[ast::ty_param]), - scope_foreign_item(@ast::foreign_item), - scope_loop(@ast::local), // there's only 1 decl per loop. - scope_block(ast::blk, @mut uint, @mut uint), - scope_arm(ast::arm), - scope_method(node_id, ~[ast::ty_param]), -} - -type scopes = @list<scope>; - -fn top_scope() -> scopes { - @cons(scope_crate, @cons(scope_toplevel, @nil)) -} - -enum import_state { - todo(ast::ident, @~[ast::ident], span, scopes), - is_glob(@~[ast::ident], scopes, span), - resolving(span), - resolved(option<def>, /* value */ - option<def>, /* type */ - option<def>, /* module */ - @~[@_impl], /* impls */ - /* used for reporting unused import warning */ - ast::ident, span), -} - -enum glob_import_state { - glob_resolving(span), - glob_resolved(option<def>, /* value */ - option<def>, /* type */ - option<def>), /* module */ -} - -type ext_hash = hashmap<{did: def_id, ident: ast::ident, ns: namespace}, def>; - -fn new_ext_hash() -> ext_hash { - type key = {did: def_id, ident: ast::ident, ns: namespace}; - fn hash(v: key) -> uint { - str::hash(*v.ident) + ast_util::hash_def(v.did) + v.ns as uint - } - fn eq(v1: key, v2: key) -> bool { - ret ast_util::def_eq(v1.did, v2.did) && - str::eq(*v1.ident, *v2.ident) && v1.ns == v2.ns; - } - std::map::hashmap(hash, |a, b| a == b) -} - -enum mod_index_entry { - mie_view_item(ident, node_id, span), - mie_import_ident(node_id, span), - mie_item(@ast::item), - mie_foreign_item(@ast::foreign_item), - mie_enum_variant(/* variant index */uint, - /*parts of enum item*/ ~[variant], - node_id, span), -} - -type mod_index = hashmap<ident, @list<mod_index_entry>>; - -// A tuple of an imported def and the view_path from its originating import -type glob_imp_def = {def: def, path: @ast::view_path}; - -type indexed_mod = { - m: option<ast::_mod>, - index: mod_index, - glob_imports: dvec<glob_imp_def>, - mut globbed_exports: ~[ident], - glob_imported_names: hashmap<ident, glob_import_state>, - path: ~str -}; - /* foreign modules can't contain enums, and we don't store their ASTs because we only need to look at them to determine exports, which they can't control.*/ @@ -116,2047 +40,6 @@ type ext_map = hashmap<def_id, ~[ident]>; type impl_map = hashmap<node_id, iscopes>; type impl_cache = hashmap<def_id, option<@~[@_impl]>>; -type exp = {reexp: bool, id: def_id}; -type exp_map = hashmap<node_id, ~[exp]>; - -type env = - {cstore: cstore::cstore, - def_map: def_map, - ast_map: ast_map::map, - imports: hashmap<node_id, import_state>, - exp_map: exp_map, - mod_map: hashmap<node_id, @indexed_mod>, - block_map: hashmap<node_id, ~[glob_imp_def]>, - ext_map: ext_map, - impl_map: impl_map, - impl_cache: impl_cache, - ext_cache: ext_hash, - used_imports: {mut track: bool, - mut data: ~[node_id]}, - reported: dvec<{ident: ast::ident, sc: scope}>, - mut ignored_imports: ~[node_id], - mut current_tp: option<uint>, - mut resolve_unexported: bool, - sess: session}; - - -// Used to distinguish between lookups from outside and from inside modules, -// since export restrictions should only be applied for the former. -enum dir { inside, outside, } - -enum namespace { ns_val, ns_type, ns_module, } - -fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) -> - {def_map: def_map, exp_map: exp_map, impl_map: impl_map} { - let e = create_env(sess, amap); - map_crate(e, crate); - resolve_imports(*e); - check_exports(e); - resolve_names(e, crate); - resolve_impls(e, crate); - // check_for_collisions must happen after resolve_names so we - // don't complain if a pattern uses the same nullary enum twice - check_for_collisions(e, *crate); - - // FIXME: move this to the lint pass when rewriting resolve. (#1634) - for sess.opts.lint_opts.each |pair| { - let (lint,level) = pair; - if lint == lint::unused_imports && level != lint::ignore { - check_unused_imports(e, level); - break; - } - } - - ret {def_map: e.def_map, exp_map: e.exp_map, impl_map: e.impl_map}; -} - -fn create_env(sess: session, amap: ast_map::map) -> @env { - @{cstore: sess.cstore, - def_map: int_hash(), - ast_map: amap, - imports: int_hash(), - exp_map: int_hash(), - mod_map: int_hash(), - block_map: int_hash(), - ext_map: new_def_hash(), - impl_map: int_hash(), - impl_cache: new_def_hash(), - ext_cache: new_ext_hash(), - used_imports: {mut track: false, mut data: ~[]}, - reported: dvec(), - mut ignored_imports: ~[], - mut current_tp: none, - mut resolve_unexported: false, - sess: sess} -} - -fn iter_export_paths(vi: ast::view_item, f: fn(vp: @ast::view_path)) { - alt vi.node { - ast::view_item_export(vps) { - for vps.each |vp| { - f(vp); - } - } - _ {} - } -} - -fn iter_import_paths(vi: ast::view_item, f: fn(vp: @ast::view_path)) { - alt vi.node { - ast::view_item_import(vps) { - for vps.each |vp| { f(vp);} - } - _ {} - } -} - -fn iter_effective_import_paths(vi: ast::view_item, - f: fn(vp: @ast::view_path)) { - iter_import_paths(vi, f); - do iter_export_paths(vi) |vp| { - alt vp.node { - ast::view_path_simple(_, _, _) { } - // FIXME (but also see #1893): support uniform ident-list exports - // eventually; at the moment they have half a meaning as reaching - // into tags. - ast::view_path_list(_, _, _) {} - ast::view_path_glob(_,_) { - f(vp); - } - } - } -} - -// Locate all modules and imports and index them, so that the next passes can -// resolve through them. -fn map_crate(e: @env, c: @ast::crate) { - - fn index_vi(e: @env, i: @ast::view_item, &&sc: scopes, _v: vt<scopes>) { - do iter_effective_import_paths(*i) |vp| { - alt vp.node { - ast::view_path_simple(name, path, id) { - e.imports.insert(id, todo(name, @path.idents, vp.span, - sc)); - } - ast::view_path_glob(path, id) { - e.imports.insert(id, is_glob(@path.idents, sc, vp.span)); - } - ast::view_path_list(mod_path, idents, _) { - for idents.each |ident| { - let t = todo(ident.node.name, - @(vec::append_one(mod_path.idents, - ident.node.name)), - ident.span, sc); - e.imports.insert(ident.node.id, t); - } - } - } - } - } - - fn path_from_scope(sc: scopes, n: ~str) -> ~str { - let mut path = n + ~"::"; - do list::iter(sc) |s| { - alt s { - scope_item(i) { path = *i.ident + ~"::" + path; } - _ {} - } - } - path - } - - fn index_i(e: @env, i: @ast::item, &&sc: scopes, v: vt<scopes>) { - visit_item_with_scope(e, i, sc, v); - alt i.node { - ast::item_mod(md) { - e.mod_map.insert(i.id, - @{m: some(md), - index: index_mod(md), - glob_imports: dvec(), - mut globbed_exports: ~[], - glob_imported_names: box_str_hash(), - path: path_from_scope(sc, *i.ident)}); - } - ast::item_foreign_mod(nmd) { - e.mod_map.insert(i.id, - @{m: none::<ast::_mod>, - index: index_nmod(nmd), - glob_imports: dvec(), - mut globbed_exports: ~[], - glob_imported_names: box_str_hash(), - path: path_from_scope(sc, *i.ident)}); - } - _ { } - } - } - - // Note: a glob export works as an implicit import, along with a - // re-export of anything that was exported at the glob-target location. - // So we wind up reusing the glob-import machinery when looking at - // glob exports. They just do re-exporting in a later step. - fn link_glob(e: @env, vi: @ast::view_item, &&sc: scopes, _v: vt<scopes>) { - do iter_effective_import_paths(*vi) |vp| { - alt vp.node { - ast::view_path_glob(path, _) { - alt follow_import(*e, sc, path.idents, vp.span) { - some(imp) { - let glob = {def: imp, path: vp}; - alt list::head(sc) { - scope_item(i) { - e.mod_map.get(i.id).glob_imports.push(glob); - } - scope_block(b, _, _) { - let globs = alt e.block_map.find(b.node.id) { - some(globs) { vec::append_one(globs, glob) } - none { ~[glob] } - }; - e.block_map.insert(b.node.id, globs); - } - scope_crate { - e.mod_map.get(ast::crate_node_id). - glob_imports.push(glob); - } - _ { e.sess.span_bug(vi.span, ~"unexpected scope in a \ - glob import"); } - } - } - _ { } - } - } - _ { } - } - } - } - - // First, find all the modules, and index the names that they contain - let v_map_mod = - @{visit_view_item: |a,b,c| index_vi(e, a, b, c), - visit_item: |a,b,c| index_i(e, a, b, c), - visit_block: visit_block_with_scope - with *visit::default_visitor::<scopes>()}; - visit::visit_crate(*c, top_scope(), visit::mk_vt(v_map_mod)); - - // Register the top-level mod - e.mod_map.insert(ast::crate_node_id, - @{m: some(c.node.module), - index: index_mod(c.node.module), - glob_imports: dvec(), - mut globbed_exports: ~[], - glob_imported_names: box_str_hash(), - path: ~""}); - - // Next, assemble the links for globbed imports and exports. - let v_link_glob = - @{visit_view_item: |a,b,c| link_glob(e, a, b, c), - visit_block: visit_block_with_scope, - visit_item: |a,b,c| visit_item_with_scope(e, a, b, c) - with *visit::default_visitor::<scopes>()}; - visit::visit_crate(*c, top_scope(), visit::mk_vt(v_link_glob)); - -} - -fn resolve_imports(e: env) { - e.used_imports.track = true; - for e.imports.each |id, v| { - alt check v { - todo(name, path, span, scopes) { - resolve_import(e, id, name, *path, span, scopes); - } - resolved(_, _, _, _, _, _) | is_glob(_, _, _) { } - } - } - e.used_imports.track = false; - e.sess.abort_if_errors(); -} - -// FIXME (#1634): move this to the lint pass when rewriting resolve. It's -// using lint-specific control flags presently but resolve-specific data -// structures. Should use the general lint framework (with scopes, attrs). -fn check_unused_imports(e: @env, level: lint::level) { - for e.imports.each |k, v| { - alt v { - resolved(_, _, _, _, name, sp) { - if !vec::contains(e.used_imports.data, k) { - alt level { - lint::warn { - e.sess.span_warn(sp, ~"unused import " + *name); - } - lint::error { - e.sess.span_err(sp, ~"unused import " + *name); - } - lint::ignore { - } - } - } - } - _ { } - } - }; -} - -fn resolve_capture_item(e: @env, sc: scopes, cap_item: ast::capture_item) { - let dcur = lookup_in_scope_strict( - *e, sc, cap_item.span, cap_item.name, ns_val); - maybe_insert(e, cap_item.id, dcur); -} - -fn maybe_insert(e: @env, id: node_id, def: option<def>) { - alt def { - some(df) { e.def_map.insert(id, df); } - _ {} - } -} - -fn resolve_trait_ref(p: @trait_ref, sc: scopes, e: @env) { - maybe_insert(e, p.ref_id, - lookup_path_strict(*e, sc, p.path.span, p.path, ns_type)); - maybe_insert(e, p.impl_id, - lookup_path_strict(*e, sc, p.path.span, p.path, ns_type)); - -} - -fn resolve_names(e: @env, c: @ast::crate) { - e.used_imports.track = true; - let v = - @{visit_foreign_item: visit_foreign_item_with_scope, - visit_item: |a,b,c| walk_item(e, a, b, c), - visit_block: visit_block_with_scope, - visit_decl: visit_decl_with_scope, - visit_arm: visit_arm_with_scope, - visit_local: |a,b,c| visit_local_with_scope(e, a, b, c), - visit_pat: |a,b,c| walk_pat(e, a, b, c), - visit_expr: |a,b,c| walk_expr(e, a, b ,c), - visit_ty: |a,b,c| walk_ty(e, a, b, c), - visit_ty_params: |a,b,c| walk_tps(e, a, b, c), - visit_fn: |a,b,c,d,f,g,h| { - visit_fn_with_scope(e, a, b, c, d, f, g, h) - } - with *visit::default_visitor()}; - visit::visit_crate(*c, top_scope(), visit::mk_vt(v)); - e.used_imports.track = false; - e.sess.abort_if_errors(); - - fn walk_item(e: @env, i: @ast::item, &&sc: scopes, v: vt<scopes>) { - visit_item_with_scope(e, i, sc, v); - alt i.node { - /* At this point, the code knows what traits the trait refs - refer to, so it's possible to resolve them. - */ - ast::item_impl(_, t, _, _) { - t.iter(|p| resolve_trait_ref(p, sc, e)); - } - ast::item_class(_, traits, _, _, _) { - for traits.each |p| { - resolve_trait_ref(p, sc, e); - } - } - _ {} - } - } - - fn walk_expr(e: @env, exp: @ast::expr, &&sc: scopes, v: vt<scopes>) { - visit::visit_expr(exp, sc, v); - alt exp.node { - ast::expr_path(p) { - maybe_insert(e, exp.id, - lookup_path_strict(*e, sc, exp.span, p, ns_val)); - } - ast::expr_fn(_, _, _, cap_clause) | - ast::expr_fn_block(_, _, cap_clause) { - for (*cap_clause).each |ci| { - resolve_capture_item(e, sc, ci); - } - } - _ { } - } - } - fn walk_ty(e: @env, t: @ast::ty, &&sc: scopes, v: vt<scopes>) { - visit::visit_ty(t, sc, v); - alt t.node { - ast::ty_path(p, id) { - maybe_insert(e, id, - lookup_path_strict(*e, sc, t.span, p, ns_type)); - } - _ { } - } - } - fn walk_tps(e: @env, tps: ~[ast::ty_param], - &&sc: scopes, v: vt<scopes>) { - let outer_current_tp = e.current_tp; - let mut current = 0u; - for tps.each |tp| { - e.current_tp = some(current); - for vec::each(*tp.bounds) |bound| { - alt bound { - bound_trait(t) { v.visit_ty(t, sc, v); } - _ {} - } - } - current += 1u; - } - e.current_tp = outer_current_tp; - } - fn walk_constr(e: @env, p: @ast::path, sp: span, id: node_id, - &&sc: scopes, _v: vt<scopes>) { - maybe_insert(e, id, lookup_path_strict(*e, sc, sp, p, ns_val)); - } - fn walk_pat(e: @env, pat: @ast::pat, &&sc: scopes, v: vt<scopes>) { - visit::visit_pat(pat, sc, v); - alt pat.node { - ast::pat_enum(p, _) { - alt lookup_path_strict(*e, sc, p.span, p, ns_val) { - some(fnd@ast::def_variant(_,_)) { - e.def_map.insert(pat.id, fnd); - } - _ { - e.sess.span_err(p.span, - ~"not an enum variant: " + - ast_util::path_name(p)); - } - } - } - /* Here we determine whether a given pat_ident binds a new - variable or refers to a nullary enum. */ - ast::pat_ident(p, none) { - alt lookup_in_scope(*e, sc, p.span, path_to_ident(p), - ns_val, false) { - some(fnd@ast::def_variant(_,_)) { - e.def_map.insert(pat.id, fnd); - } - some(fnd@ast::def_const(_)) { - e.sess.span_err(p.span, ~"pattern variable conflicts \ - with constant '" + *path_to_ident(p) + ~"'"); - } - // Binds a var -- nothing needs to be done - _ {} - } - } - _ { } - } - } -} - - -// Visit helper functions -/* - This is used in more than one context, thus should only call generic - visit methods. Called both from map_crate and resolve_names. - */ -fn visit_item_with_scope(e: @env, i: @ast::item, - &&sc: scopes, v: vt<scopes>) { - // Some magic here. Items with the !resolve_unexported attribute - // cause us to consider every name to be exported when resolving their - // contents. This is used to allow the test runner to run unexported - // tests. - let old_resolve_unexported = e.resolve_unexported; - e.resolve_unexported |= - attr::contains_name(attr::attr_metas(i.attrs), - ~"!resolve_unexported"); - - let sc = @cons(scope_item(i), sc); - alt i.node { - ast::item_impl(tps, ifce, sty, methods) { - v.visit_ty_params(tps, sc, v); - option::iter(ifce, |p| visit::visit_path(p.path, sc, v)); - v.visit_ty(sty, sc, v); - for methods.each |m| { - v.visit_ty_params(m.tps, sc, v); - let msc = @cons(scope_method(m.self_id, vec::append(tps, m.tps)), - sc); - v.visit_fn(visit::fk_method(m.ident, ~[], m), - m.decl, m.body, m.span, m.id, msc, v); - } - } - ast::item_trait(tps, methods) { - v.visit_ty_params(tps, sc, v); - for methods.each |m| { - visit_trait_method(m, i, tps, sc, v); - } - } - ast::item_class(tps, traits, members, ctor, m_dtor) { - v.visit_ty_params(tps, sc, v); - let class_scope = @cons(scope_item(i), sc); - /* visit the constructor... */ - let ctor_scope = @cons(scope_method(ctor.node.self_id, tps), - class_scope); - /* visit the trait refs in the class scope */ - for traits.each |p| { - visit::visit_path(p.path, class_scope, v); - } - visit_fn_with_scope(e, visit::fk_ctor(i.ident, tps, ctor.node.self_id, - local_def(i.id)), ctor.node.dec, - ctor.node.body, ctor.span, ctor.node.id, - ctor_scope, v); - do option::iter(m_dtor) |dtor| { - let dtor_scope = @cons(scope_method(dtor.node.self_id, tps), - class_scope); - - visit_fn_with_scope(e, visit::fk_dtor(tps, dtor.node.self_id, - local_def(i.id)), - ast_util::dtor_dec(), - dtor.node.body, dtor.span, dtor.node.id, - dtor_scope, v); - }; - /* visit the items */ - for members.each |cm| { - alt cm.node { - class_method(m) { - let msc = @cons(scope_method(m.self_id, - vec::append(tps, m.tps)), - class_scope); - visit_fn_with_scope(e, - visit::fk_item_fn(m.ident, tps), m.decl, m.body, - m.span, m.id, msc, v); } - instance_var(_,t,_,_,_) { v.visit_ty(t, class_scope, v); } - } - } - } - _ { visit::visit_item(i, sc, v); } - } - - e.resolve_unexported = old_resolve_unexported; -} - -fn visit_trait_method(m: trait_method, i: @ast::item, - tps: ~[ast::ty_param], sc: scopes, - v: vt<scopes>) { - alt m { - required(ty_m) { - let isc = @cons(scope_method(i.id, tps), sc); - v.visit_ty_params(ty_m.tps, isc, v); - let msc = @cons(scope_method(i.id, vec::append(tps, ty_m.tps)), sc); - for ty_m.decl.inputs.each |a| { v.visit_ty(a.ty, msc, v); } - v.visit_ty(ty_m.decl.output, msc, v); - } - provided(m) { - v.visit_ty_params(m.tps, sc, v); - let msc = @cons(scope_method(m.self_id, vec::append(tps, m.tps)), - sc); - v.visit_fn(visit::fk_method(m.ident, ~[], m), - m.decl, m.body, m.span, m.id, msc, v); - } - } -} - -fn visit_foreign_item_with_scope(ni: @ast::foreign_item, &&sc: scopes, - v: vt<scopes>) { - visit::visit_foreign_item(ni, @cons(scope_foreign_item(ni), sc), v); -} - -fn visit_fn_with_scope(e: @env, fk: visit::fn_kind, decl: ast::fn_decl, - body: ast::blk, sp: span, - id: node_id, &&sc: scopes, v: vt<scopes>) { - // is this a main fn declaration? - alt fk { - visit::fk_item_fn(nm, _) { - if is_main_name(~[ast_map::path_name(nm)]) && - !e.sess.building_library { - // This is a main function -- set it in the session - // as the main ID - e.sess.main_fn = some((id, sp)); - } - } - _ { /* fallthrough */ } - } - - // here's where we need to set up the mapping - // for f's constrs in the table. - let scope = alt fk { - visit::fk_item_fn(_, tps) | visit::fk_method(_, tps, _) - | visit::fk_ctor(_, tps, _, _) | visit::fk_dtor(tps, _, _) { - scope_bare_fn(decl, id, tps) } - visit::fk_anon(ast::proto_bare, _) { - scope_bare_fn(decl, id, ~[]) } - visit::fk_anon(_, _) | visit::fk_fn_block(_) { - scope_fn_expr(decl, id, ~[]) } - }; - - visit::visit_fn(fk, decl, body, sp, id, @cons(scope, sc), v); -} - -fn visit_block_with_scope(b: ast::blk, &&sc: scopes, v: vt<scopes>) { - let pos = @mut 0u, loc = @mut 0u; - let block_sc = @cons(scope_block(b, pos, loc), sc); - for b.node.view_items.each |vi| { v.visit_view_item(vi, block_sc, v); } - for b.node.stmts.each |stmt| { - v.visit_stmt(stmt, block_sc, v);; - *pos += 1u;; - *loc = 0u; - } - visit::visit_expr_opt(b.node.expr, block_sc, v); -} - -fn visit_decl_with_scope(d: @decl, &&sc: scopes, v: vt<scopes>) { - let loc_pos = alt list::head(sc) { - scope_block(_, _, pos) { pos } - _ { @mut 0u } - }; - alt d.node { - decl_local(locs) { - for locs.each |loc| { v.visit_local(loc, sc, v);; *loc_pos += 1u; } - } - decl_item(it) { v.visit_item(it, sc, v); } - } -} - -fn visit_arm_with_scope(a: ast::arm, &&sc: scopes, v: vt<scopes>) { - for a.pats.each |p| { v.visit_pat(p, sc, v); } - let sc_inner = @cons(scope_arm(a), sc); - visit::visit_expr_opt(a.guard, sc_inner, v); - v.visit_block(a.body, sc_inner, v); -} - -// This is only for irrefutable patterns (e.g. ones that appear in a let) -// So if x occurs, and x is already known to be a enum, that's always an error -fn visit_local_with_scope(e: @env, loc: @local, &&sc: scopes, v:vt<scopes>) { - // Check whether the given local has the same name as a enum that's in - // scope. We disallow this, in order to make alt patterns consisting of a - // single identifier unambiguous (does the pattern "foo" refer to enum - // foo, or is it binding a new name foo?) - do ast_util::walk_pat(loc.node.pat) |p| { - alt p.node { - pat_ident(path, _) { - alt lookup_in_scope(*e, sc, loc.span, path_to_ident(path), - ns_val, false) { - some(ast::def_variant(enum_id, variant_id)) { - // Declaration shadows an enum that's in scope. - // That's an error. - e.sess.span_err(loc.span, - #fmt("declaration of `%s` shadows an \ - enum that's in scope", - *path_to_ident(path))); - } - _ {} - } - } - _ {} - } - } - visit::visit_local(loc, sc, v); -} - - -fn follow_import(e: env, &&sc: scopes, path: ~[ident], sp: span) -> - option<def> { - let path_len = vec::len(path); - let mut dcur = lookup_in_scope_strict(e, sc, sp, path[0], ns_module); - let mut i = 1u; - loop { - alt copy dcur { - some(dcur_def) { - if i == path_len { break; } - dcur = - lookup_in_mod_strict(e, dcur_def, sp, path[i], - ns_module, outside); - i += 1u; - } - none { break; } - } - } - if i == path_len { - alt dcur { - some(ast::def_mod(_)) | some(ast::def_foreign_mod(_)) { ret dcur; } - _ { - e.sess.span_err(sp, str::connect(path.map(|x|*x), ~"::") + - ~" does not name a module."); - ret none; - } - } - } else { ret none; } -} - -// Import resolution -fn resolve_import(e: env, n_id: node_id, name: ast::ident, - ids: ~[ast::ident], sp: codemap::span, &&sc: scopes) { - fn register(e: env, id: node_id, cx: ctxt, sp: codemap::span, - name: ast::ident, lookup: fn(namespace) -> option<def>, - impls: ~[@_impl]) { - let val = lookup(ns_val), typ = lookup(ns_type), - md = lookup(ns_module); - 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)); - } - } - // Temporarily disable this import and the imports coming after during - // resolution of this import. - fn find_imports_after(e: env, id: node_id, &&sc: scopes) -> ~[node_id] { - fn lst(my_id: node_id, vis: ~[@view_item]) -> ~[node_id] { - let mut imports = ~[], found = false; - for vis.each |vi| { - do iter_effective_import_paths(*vi) |vp| { - alt vp.node { - view_path_simple(_, _, id) - | view_path_glob(_, id) { - if id == my_id { found = true; } - if found { vec::push(imports, id); } - } - view_path_list(_, ids, _) { - for ids.each |id| { - if id.node.id == my_id { found = true; } - if found { vec::push(imports, id.node.id); } - } - } - } - } - } - imports - } - alt *sc { - cons(scope_item(@{node: item_mod(m), _}), _) { - lst(id, m.view_items) - } - cons(scope_item(@{node: item_foreign_mod(m), _}), _) { - lst(id, m.view_items) - } - cons(scope_block(b, _, _), _) { - lst(id, b.node.view_items) - } - cons(scope_crate, _) { - lst(id, - option::get(e.mod_map.get(ast::crate_node_id).m).view_items) - } - _ { - e.sess.bug(~"find_imports_after: nil or unexpected scope"); - } - } - } - // This function has cleanup code at the end. Do not return without going - // through that. - e.imports.insert(n_id, resolving(sp)); - let mut ignored = find_imports_after(e, n_id, sc); - e.ignored_imports <-> ignored; - let n_idents = vec::len(ids); - let end_id = ids[n_idents - 1u]; - if n_idents == 1u { - register(e, n_id, in_scope(sc), sp, name, - |ns| lookup_in_scope(e, sc, sp, end_id, ns, true), ~[]); - } else { - alt lookup_in_scope(e, sc, sp, ids[0], ns_module, true) { - none { - unresolved_err(e, in_scope(sc), sp, ids[0], ns_name(ns_module)); - } - some(dcur_) { - let mut dcur = dcur_, i = 1u; - loop { - if i == n_idents - 1u { - let mut impls = ~[]; - find_impls_in_mod(e, dcur, impls, some(end_id)); - register(e, n_id, in_mod(dcur), sp, name, |ns| { - lookup_in_mod(e, dcur, sp, end_id, ns, outside) - }, impls); - break; - } else { - dcur = alt lookup_in_mod(e, dcur, sp, ids[i], ns_module, - outside) { - some(dcur) { dcur } - none { - unresolved_err(e, in_mod(dcur), sp, ids[i], - ns_name(ns_module)); - break; - } - }; - i += 1u; - } - } - } - } - } - e.ignored_imports <-> ignored; - // If we couldn't resolve the import, don't leave it in a partially - // resolved state, to avoid having it reported later as a cyclic - // import - alt e.imports.find(n_id) { - some(resolving(sp)) { - e.imports.insert(n_id, resolved(none, none, none, @~[], @~"", sp)); - } - _ { } - } -} - - -// Utilities -fn ns_name(ns: namespace) -> ~str { - alt ns { - ns_type { ~"typename" } - ns_val { ~"name" } - ns_module { ~"modulename" } - } -} - -enum ctxt { in_mod(def), in_scope(scopes), } - -fn unresolved_err(e: env, cx: ctxt, sp: span, name: ident, kind: ~str) { - fn find_fn_or_mod_scope(sc: scopes) -> option<scope> { - for list::each(sc) |cur| { - alt cur { - scope_crate | scope_bare_fn(_, _, _) | scope_fn_expr(_, _, _) | - scope_item(@{node: ast::item_mod(_), _}) { - ret some(cur); - } - _ {} - } - } - ret none; - } - let mut path = name; - alt cx { - in_scope(sc) { - alt find_fn_or_mod_scope(sc) { - some(err_scope) { - for e.reported.each |rs| { - if str::eq(*rs.ident, *name) && err_scope == rs.sc { ret; } - } - e.reported.push({ident: name, sc: err_scope}); - } - _ {} - } - } - in_mod(def) { - let did = def_id_of_def(def); - if did.crate == ast::local_crate { - path = @(e.mod_map.get(did.node).path + *path); - } else if did.node != ast::crate_node_id { - let paths = e.ext_map.get(did); - path = @str::connect(vec::append_one(paths, path).map(|x|*x), - ~"::"); - } - } - } - e.sess.span_err(sp, mk_unresolved_msg(path, kind)); -} - -fn unresolved_fatal(e: env, sp: span, id: ident, kind: ~str) -> ! { - e.sess.span_fatal(sp, mk_unresolved_msg(id, kind)); -} - -fn mk_unresolved_msg(id: ident, kind: ~str) -> ~str { - ret #fmt["unresolved %s: %s", kind, *id]; -} - -// Lookup helpers -fn lookup_path_strict(e: env, &&sc: scopes, sp: span, pth: @ast::path, - ns: namespace) -> option<def> { - let n_idents = vec::len(pth.idents); - let headns = if n_idents == 1u { ns } else { ns_module }; - - let first_scope = if pth.global { top_scope() } else { sc }; - - let dcur_ = - lookup_in_scope_strict(e, first_scope, sp, pth.idents[0], headns); - - alt dcur_ { - none { ret none; } - some(dcur__) { - let mut i = 1u; - let mut dcur = dcur__; - while i < n_idents { - let curns = if n_idents == i + 1u { ns } else { ns_module }; - alt lookup_in_mod_strict(e, dcur, sp, pth.idents[i], - curns, outside) { - none { break; } - some(thing) { dcur = thing; } - } - i += 1u; - } - ret some(dcur); - } - } -} - -fn lookup_in_scope_strict(e: env, &&sc: scopes, sp: span, name: ident, - ns: namespace) -> option<def> { - alt lookup_in_scope(e, sc, sp, name, ns, true) { - none { - unresolved_err(e, in_scope(sc), sp, name, ns_name(ns)); - ret none; - } - some(d) { ret some(d); } - } -} - -fn scope_is_fn(sc: scope) -> bool { - ret alt sc { - scope_bare_fn(_, _, _) | scope_foreign_item(_) { true } - _ { false } - }; -} - -// Returns: -// none - does not close -// some(node_id) - closes via the expr w/ node_id -fn scope_closes(sc: scope) -> option<node_id> { - alt sc { - scope_fn_expr(_, node_id, _) { some(node_id) } - _ { none } - } -} - -fn def_is_local(d: def) -> bool { - alt d { - ast::def_arg(_, _) | ast::def_local(_, _) | ast::def_binding(_) | - ast::def_upvar(_, _, _) { true } - _ { false } - } -} - -fn def_is_self(d: def) -> bool { - alt d { - ast::def_self(_) { true } - _ { false } - } -} - -fn def_is_ty_arg(d: def) -> bool { - ret alt d { ast::def_ty_param(_, _) { true } _ { false } }; -} - -fn lookup_in_scope(e: env, &&sc: scopes, sp: span, name: ident, ns: namespace, - check_capture: bool) -> option<def> { - - fn in_scope(e: env, sp: span, name: ident, s: scope, ns: namespace) -> - option<def> { - alt s { - scope_toplevel { - if ns == ns_type { - ret some(ast::def_prim_ty(alt *name { - ~"bool" { ast::ty_bool } - ~"int" { ast::ty_int(ast::ty_i) } - ~"uint" { ast::ty_uint(ast::ty_u) } - ~"float" { ast::ty_float(ast::ty_f) } - ~"str" { ast::ty_str } - ~"char" { ast::ty_int(ast::ty_char) } - ~"i8" { ast::ty_int(ast::ty_i8) } - ~"i16" { ast::ty_int(ast::ty_i16) } - ~"i32" { ast::ty_int(ast::ty_i32) } - ~"i64" { ast::ty_int(ast::ty_i64) } - ~"u8" { ast::ty_uint(ast::ty_u8) } - ~"u16" { ast::ty_uint(ast::ty_u16) } - ~"u32" { ast::ty_uint(ast::ty_u32) } - ~"u64" { ast::ty_uint(ast::ty_u64) } - ~"f32" { ast::ty_float(ast::ty_f32) } - ~"f64" { ast::ty_float(ast::ty_f64) } - _ { ret none; } - })); - } - } - scope_crate { - ret lookup_in_local_mod(e, ast::crate_node_id, sp, - name, ns, inside); - } - scope_item(it) { - alt it.node { - ast::item_impl(tps, _, _, _) { - if ns == ns_type { ret lookup_in_ty_params(e, name, tps); } - } - ast::item_enum(_, tps) | ast::item_ty(_, tps) { - if ns == ns_type { ret lookup_in_ty_params(e, name, tps); } - } - ast::item_trait(tps, _) { - if ns == ns_type { - if *name == ~"self" { - ret some(def_self(it.id)); - } - ret lookup_in_ty_params(e, name, tps); - } - } - ast::item_mod(_) { - ret lookup_in_local_mod(e, it.id, sp, name, ns, inside); - } - ast::item_foreign_mod(m) { - ret lookup_in_local_foreign_mod(e, it.id, sp, name, ns); - } - ast::item_class(tps, _, members, ctor, _) { - if ns == ns_type { - ret lookup_in_ty_params(e, name, tps); - } - if ns == ns_val && name == it.ident { - ret some(ast::def_fn(local_def(ctor.node.id), - ast::impure_fn)); - } - } - _ { } - } - } - scope_method(id, tps) { - if (*name == ~"self" && ns == ns_val) { - ret some(ast::def_self(id)); - } else if ns == ns_type { - ret lookup_in_ty_params(e, name, tps); - } - } - scope_foreign_item(it) { - alt check it.node { - ast::foreign_item_fn(decl, ty_params) { - ret lookup_in_fn(e, name, decl, ty_params, ns); - } - } - } - scope_bare_fn(decl, _, ty_params) | - scope_fn_expr(decl, _, ty_params) { - ret lookup_in_fn(e, name, decl, ty_params, ns); - } - scope_loop(local) { - if ns == ns_val { - alt lookup_in_pat(e, name, local.node.pat) { - some(nid) { ret some(ast::def_binding(nid)); } - _ { } - } - } - } - scope_block(b, pos, loc) { - ret lookup_in_block(e, name, sp, b.node, *pos, *loc, ns); - } - scope_arm(a) { - if ns == ns_val { - alt lookup_in_pat(e, name, a.pats[0]) { - some(nid) { ret some(ast::def_binding(nid)); } - _ { ret none; } - } - } - } - } - ret none; - } - let mut left_fn = false; - let mut closing = ~[]; - // Used to determine whether self is in scope - let mut left_fn_level2 = false; - let mut sc = sc; - loop { - alt *sc { - nil { ret none; } - cons(hd, tl) { - alt in_scope(e, sp, name, hd, ns) { - some(df_) { - let mut df = df_; - let local = def_is_local(df), self_scope = def_is_self(df); - if check_capture && - (left_fn && local || left_fn_level2 && self_scope - || scope_is_fn(hd) && left_fn && def_is_ty_arg(df)) { - let msg = if ns == ns_type { - ~"attempt to use a type argument out of scope" - } else { - ~"attempted dynamic environment-capture" - }; - e.sess.span_fatal(sp, msg); - } else if local || self_scope { - let mut i = vec::len(closing); - while i > 0u { - i -= 1u; - #debug["name=%s df=%?", *name, df]; - assert def_is_local(df) || def_is_self(df); - let df_id = def_id_of_def(df).node; - df = ast::def_upvar(df_id, @df, closing[i]); - } - } - ret some(df); - } - _ {} - } - if left_fn { - left_fn_level2 = true; - } else if ns != ns_module { - left_fn = scope_is_fn(hd); - alt scope_closes(hd) { - some(node_id) { vec::push(closing, node_id); } - _ { } - } - } - sc = tl; - } - } - }; -} - -fn lookup_in_ty_params(e: env, name: ident, ty_params: ~[ast::ty_param]) - -> option<def> { - let mut n = 0u; - for ty_params.each |tp| { - if str::eq(*tp.ident, *name) && alt e.current_tp { - some(cur) { n < cur } none { true } - } { ret some(ast::def_ty_param(local_def(tp.id), n)); } - n += 1u; - } - ret none; -} - -fn lookup_in_pat(e: env, name: ident, pat: @ast::pat) -> option<node_id> { - let mut found = none; - - do pat_util::pat_bindings(e.def_map, pat) |p_id, _sp, n| { - if str::eq(*path_to_ident(n), *name) - { found = some(p_id); } - }; - ret found; -} - -fn lookup_in_fn(e: env, name: ident, decl: ast::fn_decl, - ty_params: ~[ast::ty_param], - ns: namespace) -> option<def> { - alt ns { - ns_val { - for decl.inputs.each |a| { - if str::eq(*a.ident, *name) { - ret some(ast::def_arg(a.id, a.mode)); - } - } - ret none; - } - ns_type { ret lookup_in_ty_params(e, name, ty_params); } - _ { ret none; } - } -} - -fn lookup_in_block(e: env, name: ident, sp: span, b: ast::blk_, pos: uint, - loc_pos: uint, ns: namespace) -> option<def> { - - let mut i = vec::len(b.stmts); - while i > 0u { - i -= 1u; - let st = b.stmts[i]; - alt st.node { - ast::stmt_decl(d, _) { - alt d.node { - ast::decl_local(locs) { - if i <= pos { - let mut j = vec::len(locs); - while j > 0u { - j -= 1u; - let loc = locs[j]; - if ns == ns_val && (i < pos || j < loc_pos) { - alt lookup_in_pat(e, name, loc.node.pat) { - some(nid) { - ret some(ast::def_local(nid, - loc.node.is_mutbl)); - } - _ { } - } - } - } - } - } - ast::decl_item(it) { - alt it.node { - ast::item_enum(variants, _) { - if ns == ns_type { - if str::eq(*it.ident, *name) { - ret some(ast::def_ty(local_def(it.id))); - } - } else { - alt ns { - ns_val { - for variants.each |v| { - if str::eq(*v.node.name, *name) { - let i = v.node.id; - ret some(ast::def_variant - (local_def(it.id), local_def(i))); - } - } - } - _ {} - } - } - } - _ { - if str::eq(*it.ident, *name) { - let found = found_def_item(it, ns); - if !is_none(found) { - ret found; - } - } - } - } - } - } - } - _ { } - } - } - for b.view_items.each |vi| { - let mut is_import = false; - alt vi.node { - ast::view_item_import(_) { is_import = true; } - _ {} - } - - alt vi.node { - - ast::view_item_import(vps) | ast::view_item_export(vps) { - for vps.each |vp| { - alt vp.node { - ast::view_path_simple(ident, _, id) { - if is_import && name == ident { - ret lookup_import(e, id, ns); - } - } - - ast::view_path_list(path, idents, _) { - for idents.each |ident| { - if name == ident.node.name { - ret lookup_import(e, ident.node.id, ns); - } - } - } - - ast::view_path_glob(_, _) { - alt e.block_map.find(b.id) { - some(globs) { - let found = lookup_in_globs(e, globs, sp, name, - ns, inside); - if found != none { - ret found; - } - } - _ {} - } - } - } - } - } - _ { e.sess.span_bug(vi.span, ~"unexpected view_item in block"); } - } - } - ret none; -} - -fn found_def_item(i: @ast::item, ns: namespace) -> option<def> { - alt i.node { - ast::item_const(*) { - if ns == ns_val { - ret some(ast::def_const(local_def(i.id))); - } - } - ast::item_fn(decl, _, _) { - if ns == ns_val { - ret some(ast::def_fn(local_def(i.id), decl.purity)); - } - } - ast::item_mod(_) { - if ns == ns_module { ret some(ast::def_mod(local_def(i.id))); } - } - ast::item_foreign_mod(_) { - if ns == ns_module { - ret some(ast::def_foreign_mod(local_def(i.id))); - } - } - ast::item_ty(*) | item_trait(*) | item_enum(*) { - if ns == ns_type { ret some(ast::def_ty(local_def(i.id))); } - } - ast::item_class(_, _, _members, ct, _) { - alt ns { - ns_type { - ret some(ast::def_class(local_def(i.id))); - } - ns_val { - ret some(ast::def_fn(local_def(ct.node.id), - ast::impure_fn)); - } - ns_module { } - } - } - ast::item_impl(*) { /* ??? */ } - ast::item_mac(*) { /* ???? */ } - } - ret none; -} - -fn lookup_in_mod_strict(e: env, m: def, sp: span, name: ident, - ns: namespace, dr: dir) -> option<def> { - alt lookup_in_mod(e, m, sp, name, ns, dr) { - none { - unresolved_err(e, in_mod(m), sp, name, ns_name(ns)); - ret none; - } - some(d) { ret some(d); } - } -} - -fn lookup_in_mod(e: env, m: def, sp: span, name: ident, ns: namespace, - dr: dir) -> option<def> { - let defid = def_id_of_def(m); - if defid.crate != ast::local_crate { - // examining a module in an external crate - let cached = e.ext_cache.find({did: defid, ident: name, ns: ns}); - if !is_none(cached) { ret cached; } - let mut path = ~[name]; - if defid.node != ast::crate_node_id { - path = vec::append(cstore::get_path(e.cstore, defid), path); - } - alt lookup_external(e, defid.crate, path, ns) { - some(df) { - e.ext_cache.insert({did: defid, ident: name, ns: ns}, df); - ret some(df); - } - _ { ret none; } - } - } - alt m { - ast::def_mod(defid) { - ret lookup_in_local_mod(e, defid.node, sp, name, ns, dr); - } - ast::def_foreign_mod(defid) { - ret lookup_in_local_foreign_mod(e, defid.node, sp, name, ns); - } - _ { - // Precondition - e.sess.span_bug(sp, ~"lookup_in_mod was passed a non-mod def"); - } - } -} - -fn found_view_item(e: env, id: node_id) -> option<def> { - alt cstore::find_use_stmt_cnum(e.cstore, id) { - some(cnum) { - some(ast::def_mod({crate: cnum, node: ast::crate_node_id})) - } - none { - // This can happen if we didn't load external crate info. - // Rustdoc depends on this. - none - } - } -} - -fn lookup_import(e: env, n_id: node_id, ns: namespace) -> option<def> { - // Imports are simply ignored when resolving themselves. - if vec::contains(e.ignored_imports, n_id) { ret none; } - alt e.imports.get(n_id) { - todo(name, path, span, scopes) { - resolve_import(e, n_id, name, *path, span, scopes); - ret lookup_import(e, n_id, ns); - } - resolving(sp) { - e.sess.span_err(sp, ~"cyclic import"); - ret none; - } - resolved(val, typ, md, _, _, _) { - if e.used_imports.track { - vec::push(e.used_imports.data, n_id); - } - ret alt ns { ns_val { val } ns_type { typ } ns_module { md } }; - } - is_glob(_,_,_) { - e.sess.bug(~"lookup_import: can't handle is_glob"); - } - } -} - -fn lookup_in_local_foreign_mod(e: env, node_id: node_id, sp: span, id: ident, - ns: namespace) -> option<def> { - ret lookup_in_local_mod(e, node_id, sp, id, ns, inside); -} - -fn is_exported(e: env, i: ident, m: @indexed_mod) -> bool { - - alt m.m { - some(_m) { - if ast_util::is_exported(i, _m) { ret true; } - } - _ {} - } - - ret vec::contains(m.globbed_exports, i) - || e.resolve_unexported; -} - -// A list search function. Applies `f` to each element of `v`, starting from -// the first. When `f` returns `some(x)`, `list_search` returns `some(x)`. If -// `f` returns `none` for every element, `list_search` returns `none`. -fn list_search<T: copy, U: copy>(ls: @list<T>, f: fn(T) -> option<U>) - -> option<U> { - let mut ls = ls; - loop { - ls = alt *ls { - cons(hd, tl) { - let result = f(hd); - if !is_none(result) { ret result; } - tl - } - nil { ret none; } - }; - } -} - -fn lookup_in_local_mod(e: env, node_id: node_id, sp: span, id: ident, - ns: namespace, dr: dir) -> option<def> { - let inf = alt e.mod_map.find(node_id) { - some(x) { x } - none { e.sess.span_bug(sp, #fmt("lookup_in_local_mod: \ - module %d not in mod_map", node_id)); } - }; - if dr == outside && !is_exported(e, id, inf) { - // if we're in a foreign mod, then dr==inside, so inf.m is some _mod - ret none; // name is not visible - } - alt inf.index.find(id) { - none { } - some(lst) { - let found = list_search(lst, |x| lookup_in_mie(e, x, ns)); - if !is_none(found) { - ret found; - } - } - } - // not local or explicitly imported; try globs: - ret lookup_glob_in_mod(e, inf, sp, id, ns, outside); -} - -fn lookup_in_globs(e: env, globs: ~[glob_imp_def], sp: span, id: ident, - ns: namespace, dr: dir) -> option<def> { - fn lookup_in_mod_(e: env, def: glob_imp_def, sp: span, name: ident, - ns: namespace, dr: dir) -> option<glob_imp_def> { - alt def.path.node { - - ast::view_path_glob(_, id) { - if vec::contains(e.ignored_imports, id) { ret none; } - } - - _ { - e.sess.span_bug(sp, ~"lookup_in_globs: not a glob"); - } - } - alt lookup_in_mod(e, def.def, sp, name, ns, dr) { - some(d) { option::some({def: d, path: def.path}) } - none { none } - } - } - let g = copy globs; // FIXME #2405 - let matches = vec::filter_map(g, - |x| lookup_in_mod_(e, x, sp, id, ns, dr)); - if vec::len(matches) == 0u { - ret none; - } - else if vec::len(matches) == 1u { - ret some(matches[0].def); - } else { - for matches.each |match| { - let sp = match.path.span; - e.sess.span_note(sp, #fmt["'%s' is imported here", *id]); - } - e.sess.span_fatal(sp, ~"'" + *id + ~"' is glob-imported from" + - ~" multiple different modules."); - } -} - -fn lookup_glob_in_mod(e: env, info: @indexed_mod, sp: span, id: ident, - wanted_ns: namespace, dr: dir) -> option<def> { - // since we don't know what names we have in advance, - // absence takes the place of todo() - if !info.glob_imported_names.contains_key(id) { - info.glob_imported_names.insert(id, glob_resolving(sp)); - let globs = info.glob_imports.get(); - let val = lookup_in_globs(e, globs, sp, id, ns_val, dr); - let typ = lookup_in_globs(e, globs, sp, id, ns_type, dr); - let md = lookup_in_globs(e, globs, sp, id, ns_module, dr); - info.glob_imported_names.insert(id, glob_resolved(val, typ, md)); - } - alt info.glob_imported_names.get(id) { - glob_resolving(sp) { - ret none; - } - glob_resolved(val, typ, md) { - ret alt wanted_ns { - ns_val { val } - ns_type { typ } - ns_module { md } - }; - } - } -} - -fn lookup_in_mie(e: env, mie: mod_index_entry, ns: namespace) -> - option<def> { - alt mie { - mie_view_item(_, id, _) { - if ns == ns_module { ret found_view_item(e, id); } - } - mie_import_ident(id, _) { ret lookup_import(e, id, ns); } - mie_item(item) { ret found_def_item(item, ns); } - mie_enum_variant(variant_idx, variants, parent_id, parent_span) { - alt ns { - ns_val { - let vid = variants[variant_idx].node.id; - ret some(ast::def_variant(local_def(parent_id), - local_def(vid))); - } - _ { ret none; } - } - } - mie_foreign_item(foreign_item) { - alt foreign_item.node { - ast::foreign_item_fn(decl, _) { - if ns == ns_val { - ret some(ast::def_fn(local_def(foreign_item.id), - decl.purity)); - } - } - } - } - } - ret none; -} - - -// Module indexing -fn add_to_index(index: hashmap<ident, @list<mod_index_entry>>, id: ident, - ent: mod_index_entry) { - alt index.find(id) { - none { index.insert(id, @cons(ent, @nil)); } - some(prev) { index.insert(id, @cons(ent, prev)); } - } -} - -fn index_view_items(view_items: ~[@ast::view_item], - index: hashmap<ident, @list<mod_index_entry>>) { - for view_items.each |vi| { - alt vi.node { - ast::view_item_use(ident, _, id) { - add_to_index(index, ident, mie_view_item(ident, id, vi.span)); - } - _ {} - } - - do iter_effective_import_paths(*vi) |vp| { - alt vp.node { - ast::view_path_simple(ident, _, id) { - add_to_index(index, ident, mie_import_ident(id, vp.span)); - } - ast::view_path_list(_, idents, _) { - for idents.each |ident| { - add_to_index(index, ident.node.name, - mie_import_ident(ident.node.id, - ident.span)); - } - } - - // globbed imports have to be resolved lazily. - ast::view_path_glob(_, _) {} - } - } - } -} - -fn index_mod(md: ast::_mod) -> mod_index { - let index = box_str_hash::<@list<mod_index_entry>>(); - - index_view_items(md.view_items, index); - - for md.items.each |it| { - alt it.node { - ast::item_const(_, _) | ast::item_fn(_, _, _) | ast::item_mod(_) | - ast::item_foreign_mod(_) | ast::item_ty(_, _) | - ast::item_impl(*) | ast::item_trait(*) { - add_to_index(index, it.ident, mie_item(it)); - } - ast::item_enum(variants, _) { - add_to_index(index, it.ident, mie_item(it)); - let mut variant_idx: uint = 0u; - for variants.each |v| { - add_to_index(index, v.node.name, - mie_enum_variant(variant_idx, variants, - it.id, it.span)); - variant_idx += 1u; - } - } - ast::item_class(tps, _, items, ctor, _) { - // add the class name itself - add_to_index(index, it.ident, mie_item(it)); - } - ast::item_mac(*) { - /* ??? */ - } - } - } - ret index; -} - - -fn index_nmod(md: ast::foreign_mod) -> mod_index { - let index = box_str_hash::<@list<mod_index_entry>>(); - - index_view_items(md.view_items, index); - - for md.items.each |it| { - add_to_index(index, it.ident, mie_foreign_item(it)); - } - ret index; -} - - -// External lookups -fn ns_for_def(d: def) -> namespace { - alt d { - ast::def_variant(_, _) { ns_val } - ast::def_fn(_, _) | ast::def_self(_) | - ast::def_const(_) | ast::def_arg(_, _) | ast::def_local(_, _) | - ast::def_upvar(_, _, _) { ns_val } - ast::def_mod(_) | ast::def_foreign_mod(_) { ns_module } - ast::def_ty(_) | ast::def_binding(_) | ast::def_use(_) | - ast::def_ty_param(_, _) | ast::def_prim_ty(_) | ast::def_class(_) - { ns_type } - ast::def_region(_) { fail ~"regions are not handled by this pass" } - } -} - -fn lookup_external(e: env, cnum: int, ids: ~[ident], ns: namespace) -> - option<def> { - let mut result = none; - for csearch::lookup_defs(e.sess.cstore, cnum, ids).each |d| { - e.ext_map.insert(def_id_of_def(d), ids); - if ns == ns_for_def(d) { result = some(d); } - } - ret result; -} - - -// Collision detection -fn check_for_collisions(e: @env, c: ast::crate) { - // Module indices make checking those relatively simple -- just check each - // name for multiple entities in the same namespace. - for e.mod_map.each_value |val| { - for val.index.each |k, v| { check_mod_name(*e, k, v); }; - }; - // Other scopes have to be checked the hard way. - let v = - @{visit_item: |a,b,c| check_item(e, a, b, c), - visit_block: |a,b,c| check_block(e, a, b, c), - visit_arm: |a,b,c| check_arm(e, a, b, c), - visit_expr: |a,b,c| check_expr(e, a, b, c), - visit_ty: |a,b,c| check_ty(e, a, b, c) - with *visit::default_visitor()}; - visit::visit_crate(c, (), visit::mk_vt(v)); -} - -fn check_mod_name(e: env, name: ident, entries: @list<mod_index_entry>) { - let mut saw_mod = false; - let mut saw_type = false; - let mut saw_value = false; - let mut entries = entries; - fn dup(e: env, sp: span, word: ~str, name: ident) { - e.sess.span_fatal(sp, ~"duplicate definition of " + word + *name); - } - loop { - alt *entries { - cons(entry, rest) { - if !is_none(lookup_in_mie(e, entry, ns_val)) { - if saw_value { - dup(e, mie_span(entry), ~"", name); - } else { saw_value = true; } - } - if !is_none(lookup_in_mie(e, entry, ns_type)) { - if saw_type { - dup(e, mie_span(entry), ~"type ", name); - } else { saw_type = true; } - } - if !is_none(lookup_in_mie(e, entry, ns_module)) { - if saw_mod { - dup(e, mie_span(entry), ~"module ", name); - } else { saw_mod = true; } - } - entries = rest; - } - nil { break; } - } - } -} - -fn mie_span(mie: mod_index_entry) -> span { - ret alt mie { - mie_view_item(_, _, span) { span } - mie_import_ident(_, span) { span } - mie_item(item) { item.span } - mie_enum_variant(_, _, _, span) { span } - mie_foreign_item(item) { item.span } - }; -} - -fn check_item(e: @env, i: @ast::item, &&x: (), v: vt<()>) { - fn typaram_names(tps: ~[ast::ty_param]) -> ~[ident] { - let mut x: ~[ast::ident] = ~[]; - for tps.each |tp| { vec::push(x, tp.ident); } - ret x; - } - visit::visit_item(i, x, v); - alt i.node { - ast::item_fn(decl, ty_params, _) { - check_fn(*e, i.span, decl); - ensure_unique(*e, i.span, ty_params, |tp| tp.ident, - ~"type parameter"); - } - ast::item_enum(_, ty_params) { - ensure_unique(*e, i.span, ty_params, |tp| tp.ident, - ~"type parameter"); - } - ast::item_trait(_, methods) { - ensure_unique(*e, i.span, methods, |m| { - alt m { - required(ty_m) { - ty_m.ident - } - provided(m) { - m.ident - } - } - }, - ~"method"); - } - ast::item_impl(_, _, _, methods) { - ensure_unique(*e, i.span, methods, |m| m.ident, - ~"method"); - } - _ { } - } -} - -fn check_pat(e: @env, ch: checker, p: @ast::pat) { - do pat_util::pat_bindings(e.def_map, p) |_i, p_sp, n| { - add_name(ch, p_sp, path_to_ident(n)); - }; -} - -fn check_arm(e: @env, a: ast::arm, &&x: (), v: vt<()>) { - visit::visit_arm(a, x, v); - let ch0 = checker(*e, ~"binding"); - check_pat(e, ch0, a.pats[0]); - let seen0 = ch0.seen.get(); - let mut i = vec::len(a.pats); - while i > 1u { - i -= 1u; - let ch = checker(*e, ~"binding"); - check_pat(e, ch, a.pats[i]); - - // Ensure the bindings introduced in this pattern are the same as in - // the first pattern. - if ch.seen.len() != seen0.len() { - e.sess.span_err(a.pats[i].span, - ~"inconsistent number of bindings"); - } else { - for ch.seen.each |name| { - if is_none(vec::find(seen0, |x| str::eq(*name, *x))) { - // Fight the alias checker - let name_ = name; - e.sess.span_err(a.pats[i].span, - ~"binding " + *name_ + - ~" does not occur in first pattern"); - } - } - } - } -} - -fn check_block(e: @env, b: ast::blk, &&x: (), v: vt<()>) { - visit::visit_block(b, x, v); - let values = checker(*e, ~"value"); - let types = checker(*e, ~"type"); - let mods = checker(*e, ~"module"); - for b.node.stmts.each |st| { - alt st.node { - ast::stmt_decl(d, _) { - alt d.node { - ast::decl_local(locs) { - let local_values = checker(*e, ~"value"); - for locs.each |loc| { - do pat_util::pat_bindings(e.def_map, loc.node.pat) - |_i, p_sp, n| { - let ident = path_to_ident(n); - add_name(local_values, p_sp, ident); - check_name(values, p_sp, ident); - }; - } - } - ast::decl_item(it) { - alt it.node { - ast::item_enum(variants, _) { - add_name(types, it.span, it.ident); - for variants.each |v| { - add_name(values, v.span, v.node.name); - } - } - ast::item_mod(_) | ast::item_foreign_mod(_) { - add_name(mods, it.span, it.ident); - } - ast::item_const(_, _) | ast::item_fn(*) { - add_name(values, it.span, it.ident); - } - ast::item_ty(*) | ast::item_trait(*) { - add_name(types, it.span, it.ident); - } - _ { } - } - } - } - } - _ { } - } - } -} - -fn check_fn(e: env, sp: span, decl: ast::fn_decl) { - fn arg_name(a: ast::arg) -> ident { ret a.ident; } - ensure_unique(e, sp, decl.inputs, arg_name, ~"argument"); -} - -fn check_expr(e: @env, ex: @ast::expr, &&x: (), v: vt<()>) { - alt ex.node { - ast::expr_rec(fields, _) { - fn field_name(f: ast::field) -> ident { ret f.node.ident; } - ensure_unique(*e, ex.span, fields, field_name, ~"field"); - } - _ { } - } - visit::visit_expr(ex, x, v); -} - -fn check_ty(e: @env, ty: @ast::ty, &&x: (), v: vt<()>) { - alt ty.node { - ast::ty_rec(fields) { - fn field_name(f: ast::ty_field) -> ident { ret f.node.ident; } - ensure_unique(*e, ty.span, fields, field_name, ~"field"); - } - _ { } - } - visit::visit_ty(ty, x, v); -} - -type checker = @{seen: dvec<ident>, kind: ~str, sess: session}; - -fn checker(e: env, kind: ~str) -> checker { - ret @{seen: dvec(), kind: kind, sess: e.sess}; -} - -fn check_name(ch: checker, sp: span, name: ident) { - for ch.seen.each |s| { - if str::eq(*s, *name) { - ch.sess.span_fatal( - sp, ~"duplicate " + ch.kind + ~" name: " + *name); - } - } -} -fn add_name(ch: checker, sp: span, name: ident) { - check_name(ch, sp, name); - ch.seen.push(name); -} - -fn ensure_unique<T>(e: env, sp: span, elts: ~[T], id: fn(T) -> ident, - kind: ~str) { - let ch = checker(e, kind); - for elts.each |elt| { add_name(ch, sp, id(elt)); } -} - -fn check_exports(e: @env) { - - fn iter_mod(e: env, m: def, sp: span, _dr: dir, - f: fn(ident: ident, def: def)) { - let defid = def_id_of_def(m); - - if defid.crate != ast::local_crate { - // FIXME: ought to support external export-globs eventually. #2527 - e.sess.span_unimpl(sp, ~"glob-export of items in external crate"); - } else { - - let mid = def_id_of_def(m); - assert mid.crate == ast::local_crate; - let ixm = e.mod_map.get(mid.node); - - for ixm.index.each |ident, mies| { - do list::iter(mies) |mie| { - alt mie { - mie_item(item) { - let defs = - ~[ found_def_item(item, ns_val), - found_def_item(item, ns_type), - found_def_item(item, ns_module) ]; - for defs.each |d| { - alt d { - some(def) { - f(ident, def); - } - _ {} - } - } - } - _ { - let s = ~"glob-export from mod with non-items"; - e.sess.span_unimpl(sp, s); - } - } - } - } - } - } - - - - fn lookup_glob_any(e: @env, info: @indexed_mod, sp: span, - ident: ident, export_id: node_id) -> bool { - let m = lookup_glob_in_mod(*e, info, sp, ident, ns_module, inside); - let v = lookup_glob_in_mod(*e, info, sp, ident, ns_val, inside); - let t = lookup_glob_in_mod(*e, info, sp, ident, ns_type, inside); - maybe_add_reexport(e, export_id, m); - maybe_add_reexport(e, export_id, v); - maybe_add_reexport(e, export_id, t); - is_some(m) || is_some(v) || is_some(t) - } - - - fn maybe_add_reexport(e: @env, export_id: node_id, def: option<def>) { - do option::iter(def) |def| { - add_export(e, export_id, def_id_of_def(def), true); - } - } - fn add_export(e: @env, export_id: node_id, target_id: def_id, - reexp: bool) { - let found = alt e.exp_map.find(export_id) { - some(f) { f } none { ~[] } - }; - e.exp_map.insert(export_id, - vec::append_one(found, - {reexp: reexp, id: target_id})); - } - - fn check_export(e: @env, ident: ident, _mod: @indexed_mod, - export_id: node_id, vi: @view_item) { - let mut found_something = false; - if _mod.index.contains_key(ident) { - found_something = true; - let xs = _mod.index.get(ident); - do list::iter(xs) |x| { - alt x { - mie_import_ident(id, _) { - alt check e.imports.get(id) { - resolved(v, t, m, _, rid, _) { - maybe_add_reexport(e, export_id, v); - maybe_add_reexport(e, export_id, t); - maybe_add_reexport(e, export_id, m); - } - _ { e.sess.span_bug(vi.span, ~"unresolved export"); } - } - } - mie_item(@{id, _}) | mie_foreign_item(@{id, _}) | - mie_enum_variant(_, _, id, _) { - add_export(e, export_id, local_def(id), false); - } - _ { } - } - } - } - /* - This code previously used bitwise or (|=) but that was wrong, - because we need or to be lazy here. If something was already - found, we don't want to call lookup_glob_any (see #2316 for - what happens if we do) - */ - found_something = found_something || - lookup_glob_any(e, _mod, vi.span, ident, export_id); - if !found_something { - e.sess.span_warn(vi.span, - #fmt("exported item %s is not defined", *ident)); - } - } - - fn check_enum_ok(e: @env, sp:span, id: ident, _mod: @indexed_mod) - -> node_id { - alt _mod.index.find(id) { - none { - e.sess.span_fatal(sp, #fmt("undefined id %s in an export", *id)); - } - some(ms) { - let maybe_id = do list_search(ms) |m| { - alt m { - mie_item(@{node: item_enum(_, _), id, _}) { some(id) } - _ { none } - } - }; - alt maybe_id { - some(an_id) { an_id } - _ { e.sess.span_fatal(sp, #fmt("%s does not refer \ - to an enumeration", *id)); } - } - } - } - } - - fn check_export_enum_list(e: @env, export_id: node_id, _mod: @indexed_mod, - span: codemap::span, id: ast::ident, - ids: ~[ast::path_list_ident]) { - let parent_id = check_enum_ok(e, span, id, _mod); - add_export(e, export_id, local_def(parent_id), false); - for ids.each |variant_id| { - let mut found = false; - alt _mod.index.find(variant_id.node.name) { - some(ms) { - do list::iter(ms) |m| { - alt m { - mie_enum_variant(_, _, actual_parent_id, _) { - found = true; - if actual_parent_id != parent_id { - e.sess.span_err( - span, #fmt("variant %s doesn't belong to \ - enum %s", - *variant_id.node.name, *id)); - } - } - _ {} - } - } - } - _ {} - } - if !found { - e.sess.span_err(span, #fmt("%s is not a variant", - *variant_id.node.name)); - } - } - } - - for e.mod_map.each_value |_mod| { - alt _mod.m { - some(m) { - let glob_is_re_exported = int_hash(); - - for m.view_items.each |vi| { - do iter_export_paths(*vi) |vp| { - alt vp.node { - ast::view_path_simple(ident, _, id) { - check_export(e, ident, _mod, id, vi); - } - ast::view_path_list(path, ids, node_id) { - let id = if vec::len(path.idents) == 1u { - path.idents[0] - } else { - e.sess.span_fatal(vp.span, - ~"bad export name-list") - }; - check_export_enum_list(e, node_id, _mod, vp.span, id, - ids); - } - ast::view_path_glob(_, node_id) { - glob_is_re_exported.insert(node_id, ()); - } - } - } - } - // Now follow the export-glob links and fill in the - // globbed_exports and exp_map lists. - for _mod.glob_imports.each |glob| { - let id = alt check glob.path.node { - ast::view_path_glob(_, node_id) { node_id } - }; - if ! glob_is_re_exported.contains_key(id) { again; } - do iter_mod(*e, glob.def, - glob.path.span, outside) |ident, def| { - vec::push(_mod.globbed_exports, ident); - maybe_add_reexport(e, id, some(def)); - } - } - } - none { } - } - } -} // Impl resolution @@ -2172,220 +55,8 @@ type method_info = {did: def_id, n_tps: uint, ident: ast::ident}; type _impl = {did: def_id, ident: ast::ident, methods: ~[@method_info]}; type iscopes = @list<@~[@_impl]>; -fn resolve_impls(e: @env, c: @ast::crate) { - visit::visit_crate(*c, @nil, visit::mk_vt(@{ - visit_block: |a,b,c| visit_block_with_impl_scope(e, a, b, c), - visit_mod: |a,b,c,d,f| visit_mod_with_impl_scope(e, a, b, c, d, f), - visit_expr: |a,b,c| resolve_impl_in_expr(e, a, b, c) - with *visit::default_visitor() - })); -} - -fn find_impls_in_view_item(e: env, vi: @ast::view_item, - &impls: ~[@_impl], sc: option<iscopes>) { - fn lookup_imported_impls(e: env, id: node_id, - act: fn(@~[@_impl])) { - alt e.imports.get(id) { - resolved(_, _, _, is, _, _) { act(is); } - todo(name, path, span, scopes) { - resolve_import(e, id, name, *path, span, scopes); - alt check e.imports.get(id) { - resolved(_, _, _, is, _, _) { act(is); } - } - } - _ {} - } - } - - do iter_effective_import_paths(*vi) |vp| { - alt vp.node { - ast::view_path_simple(name, pt, id) { - let mut found = ~[]; - if vec::len(pt.idents) == 1u { - do option::iter(sc) |sc| { - do list::iter(sc) |level| { - if vec::len(found) == 0u { - for vec::each(*level) |imp| { - if imp.ident == pt.idents[0] { - vec::push(found, - @{ident: name with *imp}); - } - } - if vec::len(found) > 0u { - vec::push_all(impls, found); - } - } - } - } - } else { - do lookup_imported_impls(e, id) |is| { - for vec::each(*is) |i| { - vec::push(impls, @{ident: name with *i}); - } - } - } - } - - ast::view_path_list(base, names, _) { - for names.each |nm| { - lookup_imported_impls(e, nm.node.id, |is| { - vec::push_all(impls, *is); - }) - } - } - - ast::view_path_glob(ids, id) { - alt check e.imports.get(id) { - is_glob(path, sc, sp) { - alt follow_import(e, sc, *path, sp) { - some(def) { find_impls_in_mod(e, def, impls, none); } - _ {} - } - } - } - } - } - } -} - -/* - Given an item <i>, adds one record to the mutable vec - <impls> if the item is an impl; zero or more records if the - item is a class; and none otherwise. Each record describes - one interface implemented by i. - */ -fn find_impls_in_item(e: env, i: @ast::item, &impls: ~[@_impl], - name: option<ident>, - ck_exports: option<@indexed_mod>) { - alt i.node { - ast::item_impl(_, ifce, _, mthds) { - if alt name { some(n) { n == i.ident } _ { true } } && - alt ck_exports { - some(m) { is_exported(e, i.ident, m) } - _ { true } - } { - vec::push(impls, @{did: local_def(i.id), - ident: i.ident, - methods: vec::map(mthds, |m| { - @{did: local_def(m.id), - n_tps: vec::len(m.tps), - ident: m.ident} - })}); - } - } - ast::item_class(tps, ifces, items, _, _) { - let (_, mthds) = ast_util::split_class_items(items); - let n_tps = tps.len(); - do vec::iter(ifces) |p| { - // The def_id, in this case, identifies the combination of - // class and trait - vec::push(impls, @{did: local_def(p.impl_id), - ident: i.ident, - methods: vec::map(mthds, |m| { - @{did: local_def(m.id), - n_tps: n_tps + m.tps.len(), - ident: m.ident}})}); - } - } - _ {} - } -} - -fn find_impls_in_mod_by_id(e: env, defid: def_id, &impls: ~[@_impl], - name: option<ident>) { - let mut 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 mut tmp = ~[]; - let mi = e.mod_map.get(defid.node); - let md = option::get(mi.m); - for md.view_items.each |vi| { - find_impls_in_view_item(e, vi, tmp, none); - } - for md.items.each |i| { - find_impls_in_item(e, i, tmp, none, none); - } - @vec::filter(tmp, |i| is_exported(e, i.ident, mi)) - } else { - csearch::get_impls_for_mod(e.sess.cstore, defid, none) - }; - e.impl_cache.insert(defid, some(cached)); - } - } - alt name { - some(n) { - for vec::each(*cached) |im| { - if n == im.ident { vec::push(impls, im); } - } - } - _ { vec::push_all(impls, *cached); } - } -} - -fn find_impls_in_mod(e: env, m: def, &impls: ~[@_impl], - name: option<ident>) { - alt m { - ast::def_mod(defid) { - find_impls_in_mod_by_id(e, defid, impls, name); - } - _ {} - } -} - -fn visit_block_with_impl_scope(e: @env, b: ast::blk, &&sc: iscopes, - v: vt<iscopes>) { - let mut impls = ~[]; - for b.node.view_items.each |vi| { - find_impls_in_view_item(*e, vi, impls, some(sc)); - } - for b.node.stmts.each |st| { - alt st.node { - ast::stmt_decl(@{node: ast::decl_item(i), _}, _) { - find_impls_in_item(*e, i, impls, none, none); - } - _ {} - } - } - let sc = if vec::len(impls) > 0u { @cons(@impls, sc) } else { sc }; - visit::visit_block(b, sc, v); -} - -fn visit_mod_with_impl_scope(e: @env, m: ast::_mod, s: span, id: node_id, - &&sc: iscopes, v: vt<iscopes>) { - let mut impls = ~[]; - for m.view_items.each |vi| { - find_impls_in_view_item(*e, vi, impls, some(sc)); - } - for m.items.each |i| { find_impls_in_item(*e, i, impls, none, none); } - let impls = @impls; - visit::visit_mod(m, s, id, if vec::len(*impls) > 0u { - @cons(impls, sc) - } else { - 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>) { - alt x.node { - // Store the visible impls in all exprs that might need them - ast::expr_field(_, _, _) | ast::expr_path(_) | ast::expr_cast(_, _) | - ast::expr_binary(_, _, _) | ast::expr_unary(_, _) | - ast::expr_assign_op(_, _, _) | ast::expr_index(_, _) { - e.impl_map.insert(x.id, sc); - } - ast::expr_new(p, _, _) { - e.impl_map.insert(p.id, sc); - } - _ {} - } - visit::visit_expr(x, sc, v); -} +type exp = {reexp: bool, id: def_id}; +type exp_map = hashmap<node_id, ~[exp]>; // Local Variables: // mode: rust diff --git a/src/rustc/middle/trans/alt.rs b/src/rustc/middle/trans/alt.rs index 55715433d5c..9cf70d10429 100644 --- a/src/rustc/middle/trans/alt.rs +++ b/src/rustc/middle/trans/alt.rs @@ -10,8 +10,8 @@ import syntax::ast_util::{dummy_sp, path_to_ident}; import syntax::ast::def_id; import syntax::codemap::span; import syntax::print::pprust::pat_to_str; +import middle::resolve::def_map; import back::abi; -import resolve::def_map; import std::map::hashmap; import dvec::{dvec, extensions}; diff --git a/src/rustdoc/astsrv.rs b/src/rustdoc/astsrv.rs index 46884bcbe12..884ab33ee72 100644 --- a/src/rustdoc/astsrv.rs +++ b/src/rustdoc/astsrv.rs @@ -21,6 +21,7 @@ import rustc::back::link; import rustc::metadata::filesearch; import rustc::front; import rustc::middle::resolve; +import rustc::middle::resolve3; export ctxt; export ctxt_handler; @@ -115,7 +116,7 @@ fn build_ctxt(sess: session, let ast = front::test::modify_for_testing(sess, ast); let ast_map = ast_map::map_crate(sess.diagnostic(), *ast); *ignore_errors = true; - let {exp_map, impl_map, _} = resolve::resolve_crate(sess, ast_map, ast); + let {exp_map, impl_map, _} = resolve3::resolve_crate(sess, ast_map, ast); *ignore_errors = false; { diff --git a/src/rustdoc/reexport_pass.rs b/src/rustdoc/reexport_pass.rs index 188c168d7c3..75f53b7ab0a 100644 --- a/src/rustdoc/reexport_pass.rs +++ b/src/rustdoc/reexport_pass.rs @@ -270,8 +270,8 @@ fn for_each_reexported_impl( mod_id: ast::node_id ) { let all_impls = all_impls(m); - alt check *ctxt.impl_map.get(mod_id) { - list::cons(impls, @list::nil) { + alt *ctxt.impl_map.get(mod_id) { + list::cons(impls, _) { for vec::each(*impls) |i| { // This impl is not an item in the current mod if !all_impls.contains_key(i.did) { @@ -283,6 +283,9 @@ fn for_each_reexported_impl( } } } + list::nil { + // Do nothing -- mod has no impls + } } } } |
