2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-05 11:48:19 +02:00
|
|
|
import syntax::ast;
|
2011-07-19 17:52:34 -07:00
|
|
|
import syntax::ast::*;
|
2011-07-05 11:48:19 +02:00
|
|
|
import ast::ident;
|
|
|
|
import ast::fn_ident;
|
|
|
|
import ast::def;
|
|
|
|
import ast::def_id;
|
|
|
|
import ast::node_id;
|
|
|
|
import ast::local_def;
|
2011-06-19 22:41:21 +02:00
|
|
|
|
2011-07-07 22:18:38 -07:00
|
|
|
import metadata::csearch;
|
2011-07-07 21:37:56 -07:00
|
|
|
import metadata::cstore;
|
2011-05-12 17:24:54 +02:00
|
|
|
import driver::session::session;
|
2011-07-13 17:26:06 -07:00
|
|
|
import util::common::*;
|
2011-07-06 16:46:17 +02:00
|
|
|
import std::map::new_int_hash;
|
|
|
|
import std::map::new_str_hash;
|
2011-07-05 11:48:19 +02:00
|
|
|
import syntax::codemap::span;
|
|
|
|
import syntax::ast::respan;
|
2011-06-15 15:14:30 -07:00
|
|
|
import middle::ty::constr_table;
|
2011-07-05 11:48:19 +02:00
|
|
|
import syntax::visit;
|
2011-06-09 15:50:26 +02:00
|
|
|
import visit::vt;
|
2011-07-05 16:23:07 -07:00
|
|
|
import std::ivec;
|
2011-07-19 17:52:34 -07:00
|
|
|
import std::int;
|
2011-05-12 17:24:54 +02:00
|
|
|
import std::map::hashmap;
|
2011-05-25 10:10:30 -07:00
|
|
|
import std::list;
|
2011-05-12 17:24:54 +02:00
|
|
|
import std::list::list;
|
|
|
|
import std::list::nil;
|
|
|
|
import std::list::cons;
|
|
|
|
import std::option;
|
2011-07-22 11:31:43 +02:00
|
|
|
import std::option::is_none;
|
2011-05-12 17:24:54 +02:00
|
|
|
import std::option::some;
|
|
|
|
import std::option::none;
|
2011-05-17 20:41:41 +02:00
|
|
|
import std::str;
|
2011-07-19 17:52:34 -07:00
|
|
|
import syntax::print::pprust::*;
|
2010-10-06 18:36:28 -07:00
|
|
|
|
2011-06-18 23:00:56 -07:00
|
|
|
export resolve_crate;
|
|
|
|
export def_map;
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-05-09 12:40:09 +02:00
|
|
|
// Resolving happens in two passes. The first pass collects defids of all
|
|
|
|
// (internal) imports and modules, so that they can be looked up when needed,
|
|
|
|
// and then uses this information to resolve the imports. The second pass
|
|
|
|
// locates all names (in expressions, types, and alt patterns) and resolves
|
|
|
|
// them, storing the resulting def in the AST nodes.
|
|
|
|
|
2011-05-11 16:30:48 +02:00
|
|
|
// This module internally uses -1 as a def_id for the top_level module in a
|
|
|
|
// crate. The parser doesn't assign a def_id to this module.
|
|
|
|
// (FIXME See https://github.com/graydon/rust/issues/358 for the reason this
|
|
|
|
// isn't a const.)
|
2010-10-18 14:37:30 -07:00
|
|
|
tag scope {
|
2011-07-11 16:01:46 -07:00
|
|
|
scope_crate;
|
2011-05-12 17:24:54 +02:00
|
|
|
scope_item(@ast::item);
|
2011-06-28 16:11:41 -07:00
|
|
|
scope_fn(ast::fn_decl, ast::proto, ast::ty_param[]);
|
2011-05-12 17:24:54 +02:00
|
|
|
scope_native_item(@ast::native_item);
|
2011-06-16 15:58:25 -07:00
|
|
|
scope_loop(@ast::local); // there's only 1 decl per loop.
|
2011-07-25 14:16:12 -07:00
|
|
|
scope_block(ast::blk);
|
2011-05-12 17:24:54 +02:00
|
|
|
scope_arm(ast::arm);
|
2010-10-18 14:37:30 -07:00
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
type scopes = list[scope];
|
2010-10-18 14:37:30 -07:00
|
|
|
|
2011-05-09 12:40:09 +02:00
|
|
|
tag import_state {
|
2011-06-09 15:50:26 +02:00
|
|
|
todo(@ast::view_item, scopes); // only used for explicit imports
|
2011-05-09 12:40:09 +02:00
|
|
|
resolving(span);
|
2011-07-08 16:04:40 +02:00
|
|
|
resolved(option::t[def], /* value */
|
|
|
|
option::t[def], /* type */
|
|
|
|
option::t[def]); /* module */
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-11 12:21:09 +02:00
|
|
|
|
2011-07-26 14:06:02 +02:00
|
|
|
type ext_hash = hashmap[rec(def_id did, str ident, namespace ns), def];
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-05-11 12:21:09 +02:00
|
|
|
fn new_ext_hash() -> ext_hash {
|
2011-07-26 14:06:02 +02:00
|
|
|
type key = rec(def_id did, str ident, namespace ns);
|
|
|
|
fn hash(&key v) -> uint {
|
|
|
|
ret str::hash(v.ident) + util::common::hash_def(v.did) +
|
|
|
|
alt (v.ns) {
|
2011-06-15 11:19:50 -07:00
|
|
|
case (ns_value) { 1u }
|
|
|
|
case (ns_type) { 2u }
|
|
|
|
case (ns_module) { 3u }
|
|
|
|
};
|
2011-05-13 15:17:24 +02:00
|
|
|
}
|
2011-07-26 14:06:02 +02:00
|
|
|
fn eq(&key v1, &key v2) ->
|
2011-06-15 11:19:50 -07:00
|
|
|
bool {
|
2011-07-26 14:06:02 +02:00
|
|
|
ret util::common::def_eq(v1.did, v2.did) &&
|
|
|
|
str::eq(v1.ident, v2.ident) && v1.ns == v2.ns;
|
2011-05-11 12:21:09 +02:00
|
|
|
}
|
2011-07-26 14:06:02 +02:00
|
|
|
ret std::map::mk_hashmap[key, def](hash, eq);
|
2011-05-11 12:21:09 +02:00
|
|
|
}
|
|
|
|
|
2011-05-11 16:30:48 +02:00
|
|
|
tag mod_index_entry {
|
2011-05-12 17:24:54 +02:00
|
|
|
mie_view_item(@ast::view_item);
|
|
|
|
mie_item(@ast::item);
|
2011-05-19 11:37:17 -07:00
|
|
|
mie_native_item(@ast::native_item);
|
2011-07-08 16:04:40 +02:00
|
|
|
mie_tag_variant(@ast::item /* tag item */, uint /* variant index */);
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
2011-05-20 15:56:23 -07:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
type mod_index = hashmap[ident, list[mod_index_entry]];
|
|
|
|
|
2011-07-08 18:41:37 -07:00
|
|
|
// A tuple of an imported def and the import stmt that brung it
|
2011-07-26 14:06:02 +02:00
|
|
|
type glob_imp_def = rec(def def, @ast::view_item item);
|
2011-07-08 18:41:37 -07:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
type indexed_mod =
|
|
|
|
rec(option::t[ast::_mod] m,
|
|
|
|
mod_index index,
|
2011-07-13 16:44:39 -07:00
|
|
|
mutable glob_imp_def[] glob_imports,
|
2011-06-15 11:19:50 -07:00
|
|
|
hashmap[str, import_state] glob_imported_names);
|
|
|
|
|
|
|
|
|
2011-05-19 11:37:17 -07:00
|
|
|
/* native modules can't contain tags, and we don't store their ASTs because we
|
|
|
|
only need to look at them to determine exports, which they can't control.*/
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-06-19 22:41:21 +02:00
|
|
|
type def_map = hashmap[node_id, def];
|
2011-05-11 16:30:48 +02:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
type env =
|
2011-07-08 18:41:37 -07:00
|
|
|
rec(cstore::cstore cstore,
|
2011-06-15 11:19:50 -07:00
|
|
|
def_map def_map,
|
2011-06-20 09:59:16 +02:00
|
|
|
ast_map::map ast_map,
|
2011-06-19 22:41:21 +02:00
|
|
|
hashmap[ast::node_id, import_state] imports,
|
|
|
|
hashmap[ast::node_id, @indexed_mod] mod_map,
|
2011-07-13 16:44:39 -07:00
|
|
|
hashmap[def_id, ident[]] ext_map,
|
2011-06-15 11:19:50 -07:00
|
|
|
ext_hash ext_cache,
|
2011-07-26 14:06:02 +02:00
|
|
|
mutable rec(str ident, scope sc)[] reported,
|
2011-06-15 11:19:50 -07:00
|
|
|
session sess);
|
2011-05-12 13:25:18 +02:00
|
|
|
|
2011-06-16 16:55:46 -07:00
|
|
|
|
2011-05-09 12:40:09 +02:00
|
|
|
// Used to distinguish between lookups from outside and from inside modules,
|
|
|
|
// since export restrictions should only be applied for the former.
|
|
|
|
tag dir { inside; outside; }
|
2010-10-07 18:34:22 -07:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
tag namespace { ns_value; ns_type; ns_module; }
|
2011-03-30 17:23:25 -07:00
|
|
|
|
2011-07-19 17:52:34 -07:00
|
|
|
fn resolve_crate(session sess, &ast_map::map amap, @ast::crate crate)
|
|
|
|
-> def_map {
|
2011-06-15 11:19:50 -07:00
|
|
|
auto e =
|
2011-07-08 18:41:37 -07:00
|
|
|
@rec(cstore=sess.get_cstore(),
|
2011-06-19 22:41:21 +02:00
|
|
|
def_map=new_int_hash[def](),
|
2011-06-20 09:59:16 +02:00
|
|
|
ast_map=amap,
|
2011-06-15 11:19:50 -07:00
|
|
|
imports=new_int_hash[import_state](),
|
|
|
|
mod_map=new_int_hash[@indexed_mod](),
|
2011-07-13 16:44:39 -07:00
|
|
|
ext_map=new_def_hash[ident[]](),
|
2011-06-15 11:19:50 -07:00
|
|
|
ext_cache=new_ext_hash(),
|
2011-07-22 11:31:43 +02:00
|
|
|
mutable reported=~[],
|
2011-06-15 11:19:50 -07:00
|
|
|
sess=sess);
|
2011-06-09 15:50:26 +02:00
|
|
|
map_crate(e, crate);
|
2011-05-09 12:40:09 +02:00
|
|
|
resolve_imports(*e);
|
2011-05-18 22:23:19 +02:00
|
|
|
check_for_collisions(e, *crate);
|
2011-06-09 15:50:26 +02:00
|
|
|
resolve_names(e, crate);
|
2011-07-19 17:52:34 -07:00
|
|
|
ret e.def_map;
|
2011-01-07 17:38:13 -05:00
|
|
|
}
|
|
|
|
|
2011-05-20 15:56:23 -07:00
|
|
|
|
2011-05-09 12:40:09 +02:00
|
|
|
// Locate all modules and imports and index them, so that the next passes can
|
|
|
|
// resolve through them.
|
2011-06-09 15:50:26 +02:00
|
|
|
fn map_crate(&@env e, &@ast::crate c) {
|
2011-05-20 15:56:23 -07:00
|
|
|
// First, find all the modules, and index the names that they contain
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
auto v_map_mod =
|
2011-06-15 11:19:50 -07:00
|
|
|
@rec(visit_view_item=bind index_vi(e, _, _, _),
|
|
|
|
visit_item=bind index_i(e, _, _, _)
|
2011-06-09 15:50:26 +02:00
|
|
|
with *visit::default_visitor[scopes]());
|
2011-07-11 16:01:46 -07:00
|
|
|
visit::visit_crate(*c, cons(scope_crate, @nil),
|
2011-07-01 14:05:54 +02:00
|
|
|
visit::mk_vt(v_map_mod));
|
2011-07-13 15:44:09 -07:00
|
|
|
// Register the top-level mod
|
2011-05-09 12:40:09 +02:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
e.mod_map.insert(-1,
|
|
|
|
@rec(m=some(c.node.module),
|
|
|
|
index=index_mod(c.node.module),
|
2011-07-13 16:44:39 -07:00
|
|
|
mutable glob_imports=~[],
|
2011-06-15 11:19:50 -07:00
|
|
|
glob_imported_names=new_str_hash[import_state]()));
|
2011-06-09 15:50:26 +02:00
|
|
|
fn index_vi(@env e, &@ast::view_item i, &scopes sc, &vt[scopes] v) {
|
2011-05-13 10:51:36 +02:00
|
|
|
alt (i.node) {
|
2011-06-19 22:41:21 +02:00
|
|
|
case (ast::view_item_import(_, ?ids, ?id)) {
|
|
|
|
e.imports.insert(id, todo(i, sc));
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
case (_) { }
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-06-09 15:50:26 +02:00
|
|
|
fn index_i(@env e, &@ast::item i, &scopes sc, &vt[scopes] v) {
|
|
|
|
visit_item_with_scope(i, sc, v);
|
2011-05-09 12:40:09 +02:00
|
|
|
alt (i.node) {
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_mod(?md)) {
|
2011-06-15 11:19:50 -07:00
|
|
|
auto s = new_str_hash[import_state]();
|
2011-06-19 22:41:21 +02:00
|
|
|
e.mod_map.insert(i.id,
|
2011-06-15 11:19:50 -07:00
|
|
|
@rec(m=some(md),
|
|
|
|
index=index_mod(md),
|
2011-07-13 16:44:39 -07:00
|
|
|
mutable glob_imports=~[],
|
2011-06-15 11:19:50 -07:00
|
|
|
glob_imported_names=s));
|
2011-01-18 15:23:11 -05:00
|
|
|
}
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_native_mod(?nmd)) {
|
2011-06-15 11:19:50 -07:00
|
|
|
auto s = new_str_hash[import_state]();
|
2011-06-19 22:41:21 +02:00
|
|
|
e.mod_map.insert(i.id,
|
2011-06-15 11:19:50 -07:00
|
|
|
@rec(m=none[ast::_mod],
|
2011-05-20 15:56:23 -07:00
|
|
|
index=index_nmod(nmd),
|
2011-07-13 16:44:39 -07:00
|
|
|
mutable glob_imports=~[],
|
2011-06-15 11:19:50 -07:00
|
|
|
glob_imported_names=s));
|
2011-05-25 11:55:48 -07:00
|
|
|
}
|
2011-06-20 09:59:16 +02:00
|
|
|
case (_) { }
|
2011-01-07 17:38:13 -05:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-20 15:56:23 -07:00
|
|
|
// Next, assemble the links for globbed imports.
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
auto v_link_glob =
|
2011-06-15 11:19:50 -07:00
|
|
|
@rec(visit_view_item=bind link_glob(e, _, _, _),
|
|
|
|
visit_item=visit_item_with_scope
|
2011-06-09 15:50:26 +02:00
|
|
|
with *visit::default_visitor[scopes]());
|
2011-07-11 16:01:46 -07:00
|
|
|
visit::visit_crate(*c, cons(scope_crate, @nil),
|
2011-07-01 14:05:54 +02:00
|
|
|
visit::mk_vt(v_link_glob));
|
2011-06-09 15:50:26 +02:00
|
|
|
fn link_glob(@env e, &@ast::view_item vi, &scopes sc, &vt[scopes] v) {
|
|
|
|
fn find_mod(@env e, scopes sc) -> @indexed_mod {
|
2011-05-25 10:10:30 -07:00
|
|
|
alt (sc) {
|
2011-05-31 00:39:19 -04:00
|
|
|
case (cons(scope_item(?i), ?tl)) {
|
2011-06-15 11:19:50 -07:00
|
|
|
alt (i.node) {
|
2011-07-11 21:23:40 +02:00
|
|
|
ast::item_mod(_) | ast::item_native_mod(_) {
|
2011-06-19 22:41:21 +02:00
|
|
|
ret e.mod_map.get(i.id);
|
2011-05-25 10:10:30 -07:00
|
|
|
}
|
2011-07-11 21:23:40 +02:00
|
|
|
_ { be find_mod(e, *tl); }
|
2011-05-25 10:10:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
case (_) {
|
|
|
|
ret e.mod_map.get(-1); //top-level
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-05-25 10:10:30 -07:00
|
|
|
}
|
2011-05-20 15:56:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
alt (vi.node) {
|
2011-07-11 21:23:40 +02:00
|
|
|
//if it really is a glob import, that is
|
|
|
|
case (ast::view_item_import_glob(?path, _)) {
|
2011-06-19 02:04:08 -07:00
|
|
|
auto imp = follow_import(*e, sc, path, vi.span);
|
|
|
|
if (option::is_some(imp)) {
|
|
|
|
find_mod(e, sc).glob_imports +=
|
2011-07-26 14:06:02 +02:00
|
|
|
~[rec(def=option::get(imp), item=vi)];
|
2011-06-19 02:04:08 -07:00
|
|
|
}
|
2011-05-20 15:56:23 -07:00
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
case (_) { }
|
2011-05-20 15:56:23 -07:00
|
|
|
}
|
|
|
|
}
|
2011-01-18 15:23:11 -05:00
|
|
|
}
|
|
|
|
|
2011-05-09 12:40:09 +02:00
|
|
|
fn resolve_imports(&env e) {
|
2011-07-26 14:06:02 +02:00
|
|
|
for each (@rec(ast::node_id key, import_state val) it
|
|
|
|
in e.imports.items()) {
|
|
|
|
alt (it.val) {
|
2011-06-15 11:19:50 -07:00
|
|
|
case (todo(?item, ?sc)) { resolve_import(e, item, sc); }
|
|
|
|
case (resolved(_, _, _)) { }
|
2011-03-29 17:01:27 -07:00
|
|
|
}
|
|
|
|
}
|
2011-06-18 23:28:29 -07:00
|
|
|
e.sess.abort_if_errors();
|
2011-03-29 17:01:27 -07:00
|
|
|
}
|
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn resolve_names(&@env e, &@ast::crate c) {
|
2011-06-15 11:19:50 -07:00
|
|
|
auto v =
|
|
|
|
@rec(visit_native_item=visit_native_item_with_scope,
|
|
|
|
visit_item=visit_item_with_scope,
|
|
|
|
visit_block=visit_block_with_scope,
|
|
|
|
visit_arm=bind walk_arm(e, _, _, _),
|
|
|
|
visit_expr=bind walk_expr(e, _, _, _),
|
|
|
|
visit_ty=bind walk_ty(e, _, _, _),
|
2011-07-19 17:52:34 -07:00
|
|
|
visit_constr=bind walk_constr(e, _, _, _, _, _),
|
2011-06-19 22:41:21 +02:00
|
|
|
visit_fn=bind visit_fn_with_scope(e, _, _, _, _, _, _, _)
|
2011-06-15 11:19:50 -07:00
|
|
|
with *visit::default_visitor());
|
2011-07-11 16:01:46 -07:00
|
|
|
visit::visit_crate(*c, cons(scope_crate, @nil), visit::mk_vt(v));
|
2011-06-19 02:04:08 -07:00
|
|
|
e.sess.abort_if_errors();
|
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn walk_expr(@env e, &@ast::expr exp, &scopes sc, &vt[scopes] v) {
|
|
|
|
visit_expr_with_scope(exp, sc, v);
|
2011-05-13 10:51:36 +02:00
|
|
|
alt (exp.node) {
|
2011-06-21 22:16:40 +02:00
|
|
|
case (ast::expr_path(?p)) {
|
|
|
|
maybe_insert(e, exp.id,
|
2011-07-11 16:01:46 -07:00
|
|
|
lookup_path_strict(*e, sc, exp.span, p.node,
|
|
|
|
ns_value));
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
case (_) { }
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-06-09 15:50:26 +02:00
|
|
|
fn walk_ty(@env e, &@ast::ty t, &scopes sc, &vt[scopes] v) {
|
|
|
|
visit::visit_ty(t, sc, v);
|
2011-05-13 10:51:36 +02:00
|
|
|
alt (t.node) {
|
2011-06-19 22:41:21 +02:00
|
|
|
case (ast::ty_path(?p, ?id)) {
|
|
|
|
maybe_insert(e, id,
|
2011-07-11 16:01:46 -07:00
|
|
|
lookup_path_strict(*e, sc, t.span, p.node,
|
|
|
|
ns_type));
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
case (_) { }
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-07-19 17:52:34 -07:00
|
|
|
fn walk_constr(@env e, &ast::path p, &span sp, node_id id,
|
|
|
|
&scopes sc, &vt[scopes] v) {
|
|
|
|
maybe_insert(e, id, lookup_path_strict(*e, sc, sp, p.node, ns_value));
|
2011-06-15 15:14:30 -07:00
|
|
|
}
|
2011-06-09 15:50:26 +02:00
|
|
|
fn walk_arm(@env e, &ast::arm a, &scopes sc, &vt[scopes] v) {
|
2011-07-08 16:27:55 +02:00
|
|
|
for (@ast::pat p in a.pats) { walk_pat(*e, sc, p); }
|
2011-06-09 15:50:26 +02:00
|
|
|
visit_arm_with_scope(a, sc, v);
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-06-09 15:50:26 +02:00
|
|
|
fn walk_pat(&env e, &scopes sc, &@ast::pat pat) {
|
2011-05-13 10:51:36 +02:00
|
|
|
alt (pat.node) {
|
2011-07-04 21:53:33 +02:00
|
|
|
case (ast::pat_tag(?p, ?children)) {
|
2011-06-15 11:19:50 -07:00
|
|
|
auto fnd =
|
2011-07-11 16:01:46 -07:00
|
|
|
lookup_path_strict(e, sc, p.span, p.node, ns_value);
|
2011-06-19 02:04:08 -07:00
|
|
|
if (option::is_some(fnd)) {
|
|
|
|
alt (option::get(fnd)) {
|
|
|
|
case (ast::def_variant(?did, ?vid)) {
|
2011-07-04 21:53:33 +02:00
|
|
|
e.def_map.insert(pat.id, option::get(fnd));
|
2011-06-19 02:04:08 -07:00
|
|
|
for (@ast::pat child in children) {
|
|
|
|
walk_pat(e, sc, child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (_) {
|
|
|
|
e.sess.span_err(p.span,
|
|
|
|
"not a tag variant: " +
|
2011-06-15 11:19:50 -07:00
|
|
|
ast::path_name(p));
|
2011-06-19 02:04:08 -07:00
|
|
|
}
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
}
|
2011-01-13 23:19:42 -05:00
|
|
|
}
|
2011-07-11 14:13:20 +02:00
|
|
|
case (ast::pat_rec(?fields, _)) {
|
|
|
|
for (ast::field_pat f in fields) { walk_pat(e, sc, f.pat); }
|
|
|
|
}
|
2011-07-13 10:50:16 +02:00
|
|
|
case (ast::pat_box(?inner)) { walk_pat(e, sc, inner); }
|
2011-06-15 11:19:50 -07:00
|
|
|
case (_) { }
|
2011-01-13 23:19:42 -05:00
|
|
|
}
|
|
|
|
}
|
2011-06-19 02:04:08 -07:00
|
|
|
|
2011-06-19 22:41:21 +02:00
|
|
|
fn maybe_insert(@env e, node_id id,
|
2011-06-19 02:04:08 -07:00
|
|
|
option::t[def] def) {
|
|
|
|
if (option::is_some(def)) {
|
|
|
|
e.def_map.insert(id, option::get(def));
|
|
|
|
}
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-01-18 15:23:11 -05:00
|
|
|
|
2011-05-13 10:51:36 +02:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
// Visit helper functions
|
2011-06-09 15:50:26 +02:00
|
|
|
fn visit_item_with_scope(&@ast::item i, &scopes sc, &vt[scopes] v) {
|
|
|
|
visit::visit_item(i, cons(scope_item(i), @sc), v);
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
|
|
|
|
fn visit_native_item_with_scope(&@ast::native_item ni, &scopes sc,
|
|
|
|
&vt[scopes] v) {
|
2011-06-09 15:50:26 +02:00
|
|
|
visit::visit_native_item(ni, cons(scope_native_item(ni), @sc), v);
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-06 19:00:00 -07:00
|
|
|
fn visit_fn_with_scope(&@env e, &ast::_fn f, &ast::ty_param[] tp, &span sp,
|
2011-06-28 17:49:15 -07:00
|
|
|
&fn_ident name, node_id id, &scopes sc,
|
2011-06-15 11:19:50 -07:00
|
|
|
&vt[scopes] v) {
|
2011-07-13 17:26:06 -07:00
|
|
|
// is this a main fn declaration?
|
|
|
|
alt (name) {
|
|
|
|
case (some(?nm)) {
|
|
|
|
if (is_main_name(~[nm]) && !e.sess.get_opts().library) {
|
|
|
|
// This is a main function -- set it in the session
|
|
|
|
// as the main ID
|
|
|
|
e.sess.set_main_id(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (_) {}
|
|
|
|
}
|
|
|
|
|
2011-06-15 15:14:30 -07:00
|
|
|
// here's where we need to set up the mapping
|
|
|
|
// for f's constrs in the table.
|
2011-06-16 16:55:46 -07:00
|
|
|
|
2011-06-15 15:14:30 -07:00
|
|
|
for (@ast::constr c in f.decl.constraints) {
|
2011-07-13 15:44:09 -07:00
|
|
|
resolve_constr(e, id, c, sc, v);
|
2011-06-15 15:14:30 -07:00
|
|
|
}
|
2011-06-19 22:41:21 +02:00
|
|
|
visit::visit_fn(f, tp, sp, name, id,
|
2011-06-28 16:11:41 -07:00
|
|
|
cons(scope_fn(f.decl, f.proto, tp), @sc), v);
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-25 14:16:12 -07:00
|
|
|
fn visit_block_with_scope(&ast::blk b, &scopes sc, &vt[scopes] v) {
|
2011-06-09 15:50:26 +02:00
|
|
|
visit::visit_block(b, cons(scope_block(b), @sc), v);
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn visit_arm_with_scope(&ast::arm a, &scopes sc, &vt[scopes] v) {
|
|
|
|
visit::visit_arm(a, cons(scope_arm(a), @sc), v);
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-06-09 15:50:26 +02:00
|
|
|
fn visit_expr_with_scope(&@ast::expr x, &scopes sc, &vt[scopes] v) {
|
2011-07-26 15:50:15 +02:00
|
|
|
alt (x.node) {
|
|
|
|
ast::expr_for(?decl, ?coll, ?blk) |
|
|
|
|
ast::expr_for_each(?decl, ?coll, ?blk) {
|
|
|
|
auto new_sc = cons[scope](scope_loop(decl), @sc);
|
|
|
|
v.visit_expr(coll, sc, v);
|
|
|
|
v.visit_local(decl, new_sc, v);
|
|
|
|
v.visit_block(blk, new_sc, v);
|
|
|
|
}
|
|
|
|
ast::expr_fn(?f) {
|
2011-06-28 16:11:41 -07:00
|
|
|
visit::visit_expr(x, cons(scope_fn(f.decl, f.proto, ~[]), @sc), v);
|
2011-07-26 15:50:15 +02:00
|
|
|
}
|
|
|
|
_ { visit::visit_expr(x, sc, v); }
|
|
|
|
};
|
2011-01-07 17:38:13 -05:00
|
|
|
}
|
|
|
|
|
2011-07-07 15:31:54 -07:00
|
|
|
fn follow_import(&env e, &scopes sc, &ident[] path, &span sp)
|
|
|
|
-> option::t[def] {
|
|
|
|
auto path_len = ivec::len(path);
|
2011-05-20 15:56:23 -07:00
|
|
|
auto dcur = lookup_in_scope_strict(e, sc, sp, path.(0), ns_module);
|
|
|
|
auto i = 1u;
|
2011-06-19 02:04:08 -07:00
|
|
|
while (true && option::is_some(dcur)) {
|
2011-05-20 15:56:23 -07:00
|
|
|
if (i == path_len) { break; }
|
2011-07-22 11:31:43 +02:00
|
|
|
dcur = lookup_in_mod_strict(e, sc, option::get(dcur),
|
2011-07-07 15:31:54 -07:00
|
|
|
sp, path.(i), ns_module, outside);
|
2011-05-20 15:56:23 -07:00
|
|
|
i += 1u;
|
|
|
|
}
|
2011-06-19 02:04:08 -07:00
|
|
|
if (i == path_len) {
|
|
|
|
alt (option::get(dcur)) {
|
2011-07-11 21:23:40 +02:00
|
|
|
ast::def_mod(_) | ast::def_native_mod(_) { ret dcur; }
|
|
|
|
_ {
|
2011-07-07 15:31:54 -07:00
|
|
|
e.sess.span_err(sp, str::connect_ivec(path, "::") +
|
2011-06-15 11:19:50 -07:00
|
|
|
" does not name a module.");
|
2011-06-19 02:04:08 -07:00
|
|
|
ret none;
|
|
|
|
}
|
2011-05-20 15:56:23 -07:00
|
|
|
}
|
2011-06-19 02:04:08 -07:00
|
|
|
} else {
|
|
|
|
ret none;
|
2011-05-20 15:56:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-19 22:41:21 +02:00
|
|
|
fn resolve_constr(@env e, node_id id, &@ast::constr c, &scopes sc,
|
2011-06-15 15:14:30 -07:00
|
|
|
&vt[scopes] v) {
|
2011-06-19 02:04:08 -07:00
|
|
|
auto new_def =
|
2011-07-11 16:01:46 -07:00
|
|
|
lookup_path_strict(*e, sc, c.span, c.node.path.node, ns_value);
|
2011-06-19 02:04:08 -07:00
|
|
|
if (option::is_some(new_def)) {
|
|
|
|
alt (option::get(new_def)) {
|
2011-06-23 18:07:58 +02:00
|
|
|
case (ast::def_fn(?pred_id, ast::pure_fn)) {
|
2011-07-19 17:52:34 -07:00
|
|
|
e.def_map.insert(c.node.id, ast::def_fn(pred_id,
|
|
|
|
ast::pure_fn));
|
2011-06-19 02:04:08 -07:00
|
|
|
}
|
|
|
|
case (_) {
|
|
|
|
e.sess.span_err(c.span,
|
|
|
|
"Non-predicate in constraint: " +
|
2011-07-19 17:52:34 -07:00
|
|
|
path_to_str(c.node.path));
|
2011-06-19 02:04:08 -07:00
|
|
|
}
|
2011-06-15 15:14:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-13 10:51:36 +02:00
|
|
|
// Import resolution
|
2011-07-22 11:31:43 +02:00
|
|
|
fn resolve_import(&env e, &@ast::view_item it, &scopes sc_in) {
|
2011-06-15 11:19:50 -07:00
|
|
|
auto defid;
|
|
|
|
auto ids;
|
2011-07-08 16:04:40 +02:00
|
|
|
auto name;
|
2011-05-09 12:40:09 +02:00
|
|
|
alt (it.node) {
|
2011-07-08 16:04:40 +02:00
|
|
|
case (ast::view_item_import(?_name, ?_ids, ?_id)) {
|
2011-06-19 22:41:21 +02:00
|
|
|
defid = local_def(_id);
|
2011-06-15 11:19:50 -07:00
|
|
|
ids = _ids;
|
2011-07-08 16:04:40 +02:00
|
|
|
name = _name;
|
2010-10-18 18:19:16 -07:00
|
|
|
}
|
|
|
|
}
|
2011-07-26 14:06:02 +02:00
|
|
|
e.imports.insert(defid.node, resolving(it.span));
|
2011-07-07 15:31:54 -07:00
|
|
|
auto n_idents = ivec::len(ids);
|
2011-05-09 12:40:09 +02:00
|
|
|
auto end_id = ids.(n_idents - 1u);
|
2011-07-08 16:04:40 +02:00
|
|
|
// Ignore the current scope if this import would shadow itself.
|
2011-07-22 11:31:43 +02:00
|
|
|
auto sc = if str::eq(name, ids.(0)) { std::list::cdr(sc_in) }
|
|
|
|
else { sc_in };
|
2011-05-09 12:40:09 +02:00
|
|
|
if (n_idents == 1u) {
|
2011-07-22 11:31:43 +02:00
|
|
|
register(e, defid, it.span, end_id, sc_in,
|
2011-07-08 16:04:40 +02:00
|
|
|
lookup_in_scope(e, sc, it.span, end_id, ns_value),
|
|
|
|
lookup_in_scope(e, sc, it.span, end_id, ns_type),
|
|
|
|
lookup_in_scope(e, sc, it.span, end_id, ns_module));
|
2011-07-26 14:06:02 +02:00
|
|
|
remove_if_unresolved(e.imports, defid.node);
|
2011-05-09 12:40:09 +02:00
|
|
|
} else {
|
2011-06-18 23:28:29 -07:00
|
|
|
auto dcur = alt(lookup_in_scope(e, sc, it.span, ids.(0), ns_module)) {
|
|
|
|
case (some(?dcur)) {
|
|
|
|
dcur
|
|
|
|
}
|
|
|
|
case (none) {
|
2011-07-22 11:31:43 +02:00
|
|
|
unresolved_err(e, sc, it.span, ids.(0), ns_name(ns_module));
|
2011-07-26 14:06:02 +02:00
|
|
|
remove_if_unresolved(e.imports, defid.node);
|
2011-06-18 23:28:29 -07:00
|
|
|
ret () // FIXME (issue #521)
|
|
|
|
}
|
|
|
|
};
|
2011-05-09 12:40:09 +02:00
|
|
|
auto i = 1u;
|
|
|
|
while (true) {
|
|
|
|
if (i == n_idents - 1u) {
|
2011-07-22 11:31:43 +02:00
|
|
|
register(e, defid, it.span, end_id, sc_in,
|
2011-05-23 18:52:55 -07:00
|
|
|
lookup_in_mod(e, dcur, it.span, end_id, ns_value,
|
|
|
|
outside),
|
|
|
|
lookup_in_mod(e, dcur, it.span, end_id, ns_type,
|
|
|
|
outside),
|
|
|
|
lookup_in_mod(e, dcur, it.span, end_id, ns_module,
|
|
|
|
outside));
|
2011-07-26 14:06:02 +02:00
|
|
|
remove_if_unresolved(e.imports, defid.node);
|
2011-05-09 12:40:09 +02:00
|
|
|
break;
|
|
|
|
} else {
|
2011-06-18 23:28:29 -07:00
|
|
|
dcur = alt (lookup_in_mod(e, dcur, it.span, ids.(i),
|
|
|
|
ns_module, outside)) {
|
|
|
|
case (some(?dcur)) {
|
|
|
|
dcur
|
|
|
|
}
|
|
|
|
case (none) {
|
2011-07-22 11:31:43 +02:00
|
|
|
unresolved_err(e, sc, it.span, ids.(i),
|
2011-06-18 23:28:29 -07:00
|
|
|
ns_name(ns_module));
|
2011-07-26 14:06:02 +02:00
|
|
|
remove_if_unresolved(e.imports, defid.node);
|
2011-06-18 23:28:29 -07:00
|
|
|
ret () // FIXME (issue #521)
|
|
|
|
}
|
|
|
|
};
|
2011-05-09 12:40:09 +02:00
|
|
|
i += 1u;
|
2011-02-07 15:07:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-07-22 11:31:43 +02:00
|
|
|
fn register(&env e, def_id defid, &span sp, &ident name, &scopes sc,
|
2011-05-13 16:46:20 +02:00
|
|
|
&option::t[def] val, &option::t[def] typ,
|
|
|
|
&option::t[def] md) {
|
2011-07-22 11:31:43 +02:00
|
|
|
if is_none(val) && is_none(typ) && is_none(md) {
|
|
|
|
unresolved_err(e, sc, sp, name, "import");
|
2011-06-18 23:28:29 -07:00
|
|
|
} else {
|
2011-07-26 14:06:02 +02:00
|
|
|
e.imports.insert(defid.node, resolved(val, typ, md));
|
2011-06-18 23:28:29 -07:00
|
|
|
}
|
|
|
|
}
|
2011-06-19 22:41:21 +02:00
|
|
|
fn remove_if_unresolved(hashmap[ast::node_id, import_state] imports,
|
|
|
|
ast::node_id node_id) {
|
2011-06-18 23:28:29 -07:00
|
|
|
// 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
|
2011-06-19 22:41:21 +02:00
|
|
|
if (imports.contains_key(node_id)) {
|
|
|
|
alt (imports.get(node_id)) {
|
2011-06-18 23:28:29 -07:00
|
|
|
case (resolving(_)) {
|
2011-06-19 22:41:21 +02:00
|
|
|
imports.remove(node_id);
|
2011-06-18 23:28:29 -07:00
|
|
|
}
|
|
|
|
case (_) { }
|
|
|
|
}
|
2011-01-01 13:13:00 -05:00
|
|
|
}
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-01-01 13:13:00 -05:00
|
|
|
|
2011-05-09 12:40:09 +02:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
// Utilities
|
2011-05-09 12:40:09 +02:00
|
|
|
fn ns_name(namespace ns) -> str {
|
|
|
|
alt (ns) {
|
|
|
|
case (ns_type) { ret "typename"; }
|
|
|
|
case (ns_value) { ret "name"; }
|
2011-05-13 16:46:20 +02:00
|
|
|
case (ns_module) { ret "modulename"; }
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-22 11:31:43 +02:00
|
|
|
fn unresolved_err(&env e, &scopes sc, &span sp, &ident name, &str kind) {
|
|
|
|
fn find_fn_or_mod_scope(scopes sc) -> scope {
|
|
|
|
while true {
|
|
|
|
alt sc {
|
|
|
|
cons(?cur, ?rest) {
|
|
|
|
alt cur {
|
2011-06-28 16:11:41 -07:00
|
|
|
scope_crate | scope_fn(_, _, _) |
|
2011-07-22 11:31:43 +02:00
|
|
|
scope_item(@{node: ast::item_mod(_), _}) {
|
|
|
|
ret cur;
|
|
|
|
}
|
|
|
|
_ { sc = *rest; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fail;
|
|
|
|
}
|
|
|
|
auto err_scope = find_fn_or_mod_scope(sc);
|
2011-07-26 14:06:02 +02:00
|
|
|
for (rec(str ident, scope sc) rs in e.reported) {
|
|
|
|
if str::eq(rs.ident, name) && err_scope == rs.sc { ret; }
|
2011-07-22 11:31:43 +02:00
|
|
|
}
|
2011-07-26 14:06:02 +02:00
|
|
|
e.reported += ~[rec(ident=name, sc=err_scope)];
|
2011-06-20 08:14:24 +02:00
|
|
|
e.sess.span_err(sp, mk_unresolved_msg(name, kind));
|
2011-06-18 23:28:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
fn unresolved_fatal(&env e, &span sp, &ident id, &str kind) -> ! {
|
|
|
|
e.sess.span_fatal(sp, mk_unresolved_msg(id, kind));
|
2011-06-18 23:28:29 -07:00
|
|
|
}
|
|
|
|
|
2011-06-18 23:28:29 -07:00
|
|
|
fn mk_unresolved_msg(&ident id, &str kind) -> str {
|
|
|
|
ret #fmt("unresolved %s: %s", kind, id);
|
|
|
|
}
|
2011-05-13 10:51:36 +02:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
// Lookup helpers
|
2011-07-11 16:01:46 -07:00
|
|
|
fn lookup_path_strict(&env e, &scopes sc, &span sp, &ast::path_ pth,
|
2011-06-19 02:04:08 -07:00
|
|
|
namespace ns) -> option::t[def] {
|
2011-07-11 16:01:46 -07:00
|
|
|
auto n_idents = ivec::len(pth.idents);
|
2011-05-13 16:46:20 +02:00
|
|
|
auto headns = if (n_idents == 1u) { ns } else { ns_module };
|
2011-07-11 16:01:46 -07:00
|
|
|
|
|
|
|
auto first_scope;
|
|
|
|
if (pth.global) {
|
|
|
|
first_scope = list::cons(scope_crate, @list::nil);
|
|
|
|
} else {
|
|
|
|
first_scope = sc;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto dcur = lookup_in_scope_strict(e, first_scope, sp, pth.idents.(0),
|
|
|
|
headns);
|
|
|
|
|
2011-05-12 13:25:18 +02:00
|
|
|
auto i = 1u;
|
2011-06-19 02:04:08 -07:00
|
|
|
while (i < n_idents && option::is_some(dcur)) {
|
2011-05-13 16:46:20 +02:00
|
|
|
auto curns = if (n_idents == i + 1u) { ns } else { ns_module };
|
2011-07-22 11:31:43 +02:00
|
|
|
dcur = lookup_in_mod_strict(e, sc, option::get(dcur),
|
2011-07-11 16:01:46 -07:00
|
|
|
sp, pth.idents.(i), curns, outside);
|
2011-05-12 13:25:18 +02:00
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
ret dcur;
|
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-06-20 08:14:24 +02:00
|
|
|
fn lookup_in_scope_strict(&env e, scopes sc, &span sp, &ident name,
|
2011-06-19 02:04:08 -07:00
|
|
|
namespace ns) -> option::t[def] {
|
2011-06-20 08:14:24 +02:00
|
|
|
alt (lookup_in_scope(e, sc, sp, name, ns)) {
|
2011-06-19 02:04:08 -07:00
|
|
|
case (none) {
|
2011-07-22 11:31:43 +02:00
|
|
|
unresolved_err(e, sc, sp, name, ns_name(ns));
|
2011-06-19 02:04:08 -07:00
|
|
|
ret none;
|
|
|
|
}
|
|
|
|
case (some(?d)) { ret some(d); }
|
2011-03-11 17:10:11 -05:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-03-11 17:10:11 -05:00
|
|
|
|
2011-05-13 11:57:58 +02:00
|
|
|
fn scope_is_fn(&scope sc) -> bool {
|
|
|
|
ret alt (sc) {
|
2011-06-28 16:11:41 -07:00
|
|
|
scope_fn(_, ast::proto_iter, _) |
|
|
|
|
scope_fn(_, ast::proto_fn, _) |
|
|
|
|
scope_native_item(_) { true }
|
|
|
|
_ { false }
|
|
|
|
};
|
2011-05-13 11:57:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn def_is_local(&def d) -> bool {
|
|
|
|
ret alt (d) {
|
2011-07-11 21:23:40 +02:00
|
|
|
ast::def_arg(_) | ast::def_local(_) | ast::def_binding(_) { true }
|
|
|
|
_ { false }
|
|
|
|
};
|
2011-05-13 11:57:58 +02:00
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-05-13 11:57:58 +02:00
|
|
|
fn def_is_obj_field(&def d) -> bool {
|
2011-06-15 11:19:50 -07:00
|
|
|
ret alt (d) { case (ast::def_obj_field(_)) { true } case (_) { false } };
|
2011-05-13 11:57:58 +02:00
|
|
|
}
|
|
|
|
|
2011-07-12 13:42:05 -07:00
|
|
|
fn def_is_ty_arg(&def d) -> bool {
|
|
|
|
ret alt(d) { case (ast::def_ty_arg(_)) { true } case (_) { false } };
|
|
|
|
}
|
|
|
|
|
2011-06-20 08:14:24 +02:00
|
|
|
fn lookup_in_scope(&env e, scopes sc, &span sp, &ident name, namespace ns) ->
|
2011-06-15 11:19:50 -07:00
|
|
|
option::t[def] {
|
2011-06-20 08:14:24 +02:00
|
|
|
fn in_scope(&env e, &span sp, &ident name, &scope s, namespace ns) ->
|
2011-06-15 11:19:50 -07:00
|
|
|
option::t[def] {
|
2010-10-18 14:37:30 -07:00
|
|
|
alt (s) {
|
2011-07-11 16:01:46 -07:00
|
|
|
case (scope_crate) {
|
2011-06-20 08:14:24 +02:00
|
|
|
ret lookup_in_local_mod(e, -1, sp, name, ns, inside);
|
2010-10-18 14:37:30 -07:00
|
|
|
}
|
|
|
|
case (scope_item(?it)) {
|
|
|
|
alt (it.node) {
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_obj(?ob, ?ty_params, _)) {
|
2011-06-20 08:14:24 +02:00
|
|
|
ret lookup_in_obj(name, ob, ty_params, ns);
|
2010-12-30 15:27:52 -08:00
|
|
|
}
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_tag(_, ?ty_params)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
if (ns == ns_type) {
|
2011-06-20 08:14:24 +02:00
|
|
|
ret lookup_in_ty_params(name, ty_params);
|
2011-02-14 13:36:20 -08:00
|
|
|
}
|
|
|
|
}
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_mod(_)) {
|
2011-06-20 08:14:24 +02:00
|
|
|
ret lookup_in_local_mod
|
|
|
|
(e, it.id, sp, name, ns, inside);
|
2010-10-18 14:37:30 -07:00
|
|
|
}
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_native_mod(?m)) {
|
2011-06-20 08:14:24 +02:00
|
|
|
ret lookup_in_local_native_mod
|
|
|
|
(e, it.id, sp, name, ns);
|
2011-02-07 15:07:27 -05:00
|
|
|
}
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_ty(_, ?ty_params)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
if (ns == ns_type) {
|
2011-06-20 08:14:24 +02:00
|
|
|
ret lookup_in_ty_params(name, ty_params);
|
2011-01-19 16:13:33 -05:00
|
|
|
}
|
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
case (_) { }
|
2010-10-18 14:37:30 -07:00
|
|
|
}
|
|
|
|
}
|
2011-02-10 14:32:22 -05:00
|
|
|
case (scope_native_item(?it)) {
|
|
|
|
alt (it.node) {
|
2011-07-06 19:00:00 -07:00
|
|
|
case (ast::native_item_fn(_, ?decl, ?ty_params)) {
|
2011-06-20 08:14:24 +02:00
|
|
|
ret lookup_in_fn(name, decl, ty_params, ns);
|
2011-02-10 14:32:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-28 16:11:41 -07:00
|
|
|
case (scope_fn(?decl, _, ?ty_params)) {
|
2011-06-20 08:14:24 +02:00
|
|
|
ret lookup_in_fn(name, decl, ty_params, ns);
|
2011-06-09 15:50:26 +02:00
|
|
|
}
|
2011-06-13 17:04:15 -07:00
|
|
|
case (scope_loop(?local)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
if (ns == ns_value) {
|
2011-06-20 08:14:24 +02:00
|
|
|
if (str::eq(local.node.ident, name)) {
|
2011-06-19 22:41:21 +02:00
|
|
|
ret some(ast::def_local(local_def(local.node.id)));
|
2011-01-20 15:17:26 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-20 08:14:24 +02:00
|
|
|
case (scope_block(?b)) { ret lookup_in_block(name, b.node, ns); }
|
2010-12-10 18:08:32 -08:00
|
|
|
case (scope_arm(?a)) {
|
2011-07-08 16:27:55 +02:00
|
|
|
if (ns == ns_value) { ret lookup_in_pat(name, *a.pats.(0)); }
|
2010-12-10 18:08:32 -08:00
|
|
|
}
|
2010-10-18 14:37:30 -07:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
ret none[def];
|
2010-10-18 14:37:30 -07:00
|
|
|
}
|
2011-05-13 11:57:58 +02:00
|
|
|
auto left_fn = false;
|
|
|
|
// Used to determine whether obj fields are in scope
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-05-13 11:57:58 +02:00
|
|
|
auto left_fn_level2 = false;
|
2011-05-09 12:40:09 +02:00
|
|
|
while (true) {
|
2011-06-15 11:19:50 -07:00
|
|
|
alt ({ sc }) {
|
|
|
|
case (nil) { ret none[def]; }
|
2011-05-31 00:39:19 -04:00
|
|
|
case (cons(?hd, ?tl)) {
|
2011-06-20 08:14:24 +02:00
|
|
|
auto fnd = in_scope(e, sp, name, hd, ns);
|
2011-07-22 11:31:43 +02:00
|
|
|
if (!is_none(fnd)) {
|
2011-05-13 11:57:58 +02:00
|
|
|
auto df = option::get(fnd);
|
2011-06-15 11:19:50 -07:00
|
|
|
if (left_fn && def_is_local(df) ||
|
2011-07-12 13:42:05 -07:00
|
|
|
left_fn_level2 && def_is_obj_field(df)
|
|
|
|
|| (scope_is_fn(hd) && left_fn
|
|
|
|
&& def_is_ty_arg(df))) {
|
|
|
|
auto msg = alt (ns) {
|
|
|
|
case (ns_type) {
|
|
|
|
"Attempt to use a type \
|
|
|
|
argument out of scope"
|
|
|
|
}
|
|
|
|
case (_) { "attempted dynamic \
|
|
|
|
environment-capture" }
|
|
|
|
};
|
|
|
|
e.sess.span_fatal(sp, msg);
|
2011-05-13 11:57:58 +02:00
|
|
|
}
|
|
|
|
ret fnd;
|
|
|
|
}
|
|
|
|
if (left_fn) { left_fn_level2 = true; }
|
2011-07-12 13:42:05 -07:00
|
|
|
if ((ns == ns_value || ns == ns_type) && !left_fn) {
|
|
|
|
left_fn = scope_is_fn(hd); }
|
2011-05-13 11:57:58 +02:00
|
|
|
sc = *tl;
|
2011-01-17 16:17:09 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-05-20 14:17:59 -07:00
|
|
|
e.sess.bug("reached unreachable code in lookup_in_scope"); // sigh
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2010-10-18 16:15:25 -07:00
|
|
|
}
|
|
|
|
|
2011-07-06 19:00:00 -07:00
|
|
|
fn lookup_in_ty_params(&ident name, &ast::ty_param[] ty_params) ->
|
2011-06-15 11:19:50 -07:00
|
|
|
option::t[def] {
|
2011-05-09 12:40:09 +02:00
|
|
|
auto i = 0u;
|
2011-05-12 17:24:54 +02:00
|
|
|
for (ast::ty_param tp in ty_params) {
|
2011-06-20 08:14:24 +02:00
|
|
|
if (str::eq(tp, name)) { ret some(ast::def_ty_arg(i)); }
|
2011-05-09 12:40:09 +02:00
|
|
|
i += 1u;
|
2010-12-12 16:47:37 -08:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
ret none[def];
|
|
|
|
}
|
2010-12-12 16:47:37 -08:00
|
|
|
|
2011-06-20 08:14:24 +02:00
|
|
|
fn lookup_in_pat(&ident name, &ast::pat pat) -> option::t[def] {
|
2011-05-11 15:26:36 +02:00
|
|
|
alt (pat.node) {
|
2011-07-04 21:53:33 +02:00
|
|
|
case (ast::pat_bind(?p_name)) {
|
2011-06-20 08:14:24 +02:00
|
|
|
if (str::eq(p_name, name)) {
|
2011-07-04 21:53:33 +02:00
|
|
|
ret some(ast::def_binding(local_def(pat.id)));
|
2011-06-19 22:41:21 +02:00
|
|
|
}
|
2011-05-11 15:26:36 +02:00
|
|
|
}
|
2011-07-04 21:53:33 +02:00
|
|
|
case (ast::pat_wild) { }
|
|
|
|
case (ast::pat_lit(_)) { }
|
|
|
|
case (ast::pat_tag(_, ?pats)) {
|
2011-05-12 17:24:54 +02:00
|
|
|
for (@ast::pat p in pats) {
|
2011-06-20 08:14:24 +02:00
|
|
|
auto found = lookup_in_pat(name, *p);
|
2011-07-22 11:31:43 +02:00
|
|
|
if (!is_none(found)) { ret found; }
|
2011-05-11 15:26:36 +02:00
|
|
|
}
|
|
|
|
}
|
2011-07-11 14:13:20 +02:00
|
|
|
case (ast::pat_rec(?fields, _)) {
|
|
|
|
for (ast::field_pat f in fields) {
|
|
|
|
auto found = lookup_in_pat(name, *f.pat);
|
2011-07-22 11:31:43 +02:00
|
|
|
if (!is_none(found)) { ret found; }
|
2011-07-11 14:13:20 +02:00
|
|
|
}
|
|
|
|
}
|
2011-07-13 10:50:16 +02:00
|
|
|
case (ast::pat_box(?inner)) { ret lookup_in_pat(name, *inner); }
|
2011-05-11 15:26:36 +02:00
|
|
|
}
|
|
|
|
ret none[def];
|
|
|
|
}
|
|
|
|
|
2011-06-20 08:14:24 +02:00
|
|
|
fn lookup_in_fn(&ident name, &ast::fn_decl decl,
|
2011-07-06 19:00:00 -07:00
|
|
|
&ast::ty_param[] ty_params,
|
2011-05-12 17:24:54 +02:00
|
|
|
namespace ns) -> option::t[def] {
|
2011-05-13 16:46:20 +02:00
|
|
|
alt (ns) {
|
|
|
|
case (ns_value) {
|
|
|
|
for (ast::arg a in decl.inputs) {
|
2011-06-20 08:14:24 +02:00
|
|
|
if (str::eq(a.ident, name)) {
|
2011-06-19 22:41:21 +02:00
|
|
|
ret some(ast::def_arg(local_def(a.id)));
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-13 16:46:20 +02:00
|
|
|
ret none[def];
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-06-20 08:14:24 +02:00
|
|
|
case (ns_type) { ret lookup_in_ty_params(name, ty_params); }
|
2011-05-13 16:46:20 +02:00
|
|
|
case (_) { ret none[def]; }
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2010-12-12 16:47:37 -08:00
|
|
|
}
|
|
|
|
|
2011-07-06 19:00:00 -07:00
|
|
|
fn lookup_in_obj(&ident name, &ast::_obj ob, &ast::ty_param[] ty_params,
|
2011-05-12 17:24:54 +02:00
|
|
|
namespace ns) -> option::t[def] {
|
2011-05-13 16:46:20 +02:00
|
|
|
alt (ns) {
|
|
|
|
case (ns_value) {
|
|
|
|
for (ast::obj_field f in ob.fields) {
|
2011-06-20 08:14:24 +02:00
|
|
|
if (str::eq(f.ident, name)) {
|
2011-06-19 22:41:21 +02:00
|
|
|
ret some(ast::def_obj_field(local_def(f.id)));
|
2011-05-13 16:46:20 +02:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-13 16:46:20 +02:00
|
|
|
ret none[def];
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-06-20 08:14:24 +02:00
|
|
|
case (ns_type) { ret lookup_in_ty_params(name, ty_params); }
|
2011-05-13 16:46:20 +02:00
|
|
|
case (_) { ret none[def]; }
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
2011-01-13 17:42:28 -08:00
|
|
|
|
2011-07-25 14:16:12 -07:00
|
|
|
fn lookup_in_block(&ident name, &ast::blk_ b, namespace ns) ->
|
2011-06-15 11:19:50 -07:00
|
|
|
option::t[def] {
|
2011-05-12 17:24:54 +02:00
|
|
|
for (@ast::stmt st in b.stmts) {
|
2011-05-11 15:10:24 +02:00
|
|
|
alt (st.node) {
|
2011-06-15 11:19:50 -07:00
|
|
|
case (ast::stmt_decl(?d, _)) {
|
2011-05-11 15:10:24 +02:00
|
|
|
alt (d.node) {
|
2011-07-22 17:19:06 +02:00
|
|
|
ast::decl_local(?locs) {
|
|
|
|
for (@ast::local loc in locs) {
|
|
|
|
if ns == ns_value && str::eq(name, loc.node.ident) {
|
|
|
|
ret some(ast::def_local
|
|
|
|
(local_def(loc.node.id)));
|
|
|
|
}
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
case (ast::decl_item(?it)) {
|
2011-05-11 15:10:24 +02:00
|
|
|
alt (it.node) {
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_tag(?variants, _)) {
|
2011-05-11 15:10:24 +02:00
|
|
|
if (ns == ns_type) {
|
2011-06-20 08:14:24 +02:00
|
|
|
if (str::eq(it.ident, name)) {
|
2011-06-19 22:41:21 +02:00
|
|
|
ret some(ast::def_ty
|
|
|
|
(local_def(it.id)));
|
2011-05-11 15:10:24 +02:00
|
|
|
}
|
2011-05-13 16:46:20 +02:00
|
|
|
} else if (ns == ns_value) {
|
2011-05-12 17:24:54 +02:00
|
|
|
for (ast::variant v in variants) {
|
2011-06-20 08:14:24 +02:00
|
|
|
if (str::eq(v.node.name, name)) {
|
2011-06-16 16:55:46 -07:00
|
|
|
auto i = v.node.id;
|
2011-06-19 22:41:21 +02:00
|
|
|
ret some(ast::def_variant
|
|
|
|
(local_def(it.id),
|
|
|
|
local_def(i)));
|
2011-05-11 15:10:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case (_) {
|
2011-06-20 08:14:24 +02:00
|
|
|
if (str::eq(it.ident, name)) {
|
2011-05-11 15:10:24 +02:00
|
|
|
auto found = found_def_item(it, ns);
|
2011-07-22 11:31:43 +02:00
|
|
|
if (!is_none(found)) {
|
2011-06-15 11:19:50 -07:00
|
|
|
ret found;
|
|
|
|
}
|
2011-05-11 15:10:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
case (_) { }
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
ret none[def];
|
|
|
|
}
|
2010-10-18 14:37:30 -07:00
|
|
|
|
2011-05-19 21:46:51 +02:00
|
|
|
fn found_def_item(&@ast::item i, namespace ns) -> option::t[def] {
|
2011-05-09 12:40:09 +02:00
|
|
|
alt (i.node) {
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_const(_, _)) {
|
2011-06-19 22:41:21 +02:00
|
|
|
if (ns == ns_value) {
|
|
|
|
ret some(ast::def_const(local_def(i.id)));
|
|
|
|
}
|
2011-01-25 18:15:19 -05:00
|
|
|
}
|
2011-06-20 17:29:54 -07:00
|
|
|
case (ast::item_fn(?f, _)) {
|
2011-06-19 22:41:21 +02:00
|
|
|
if (ns == ns_value) {
|
2011-06-20 17:29:54 -07:00
|
|
|
ret some(ast::def_fn(local_def(i.id), f.decl.purity));
|
2011-06-19 22:41:21 +02:00
|
|
|
}
|
2011-01-25 18:15:19 -05:00
|
|
|
}
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_mod(_)) {
|
2011-06-19 22:41:21 +02:00
|
|
|
if (ns == ns_module) {
|
|
|
|
ret some(ast::def_mod(local_def(i.id)));
|
|
|
|
}
|
2011-01-25 18:15:19 -05:00
|
|
|
}
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_native_mod(_)) {
|
2011-06-19 22:41:21 +02:00
|
|
|
if (ns == ns_module) {
|
|
|
|
ret some(ast::def_native_mod(local_def(i.id)));
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_ty(_, _)) {
|
2011-06-19 22:41:21 +02:00
|
|
|
if (ns == ns_type) {
|
|
|
|
ret some(ast::def_ty(local_def(i.id)));
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-06-24 18:10:40 +02:00
|
|
|
case (ast::item_res(_, _, _, ?ctor_id)) {
|
|
|
|
alt (ns) {
|
|
|
|
case (ns_value) { ret some(ast::def_fn(local_def(ctor_id),
|
|
|
|
ast::impure_fn)); }
|
|
|
|
case (ns_type) { ret some(ast::def_ty(local_def(i.id))); }
|
|
|
|
case (_) { }
|
|
|
|
}
|
|
|
|
}
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_tag(_, _)) {
|
2011-06-19 22:41:21 +02:00
|
|
|
if (ns == ns_type) {
|
|
|
|
ret some(ast::def_ty(local_def(i.id)));
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_obj(_, _, ?ctor_id)) {
|
2011-05-13 16:46:20 +02:00
|
|
|
alt (ns) {
|
2011-06-23 18:07:58 +02:00
|
|
|
case (ns_value) { ret some(ast::def_fn(local_def(ctor_id),
|
|
|
|
ast::impure_fn)); }
|
|
|
|
case (ns_type) { ret some(ast::def_ty(local_def(i.id))); }
|
2011-05-13 16:46:20 +02:00
|
|
|
case (_) { }
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
case (_) { }
|
2011-01-25 18:15:19 -05:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
ret none[def];
|
2010-10-07 18:34:22 -07:00
|
|
|
}
|
|
|
|
|
2011-07-22 11:31:43 +02:00
|
|
|
fn lookup_in_mod_strict(&env e, &scopes sc, def m, &span sp, &ident name,
|
|
|
|
namespace ns, dir dr) -> option::t[def] {
|
2011-06-20 08:14:24 +02:00
|
|
|
alt (lookup_in_mod(e, m, sp, name, ns, dr)) {
|
2011-06-19 02:04:08 -07:00
|
|
|
case (none) {
|
2011-07-22 11:31:43 +02:00
|
|
|
unresolved_err(e, sc, sp, name, ns_name(ns));
|
2011-06-19 02:04:08 -07:00
|
|
|
ret none;
|
|
|
|
}
|
|
|
|
case (some(?d)) { ret some(d); }
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-03-29 17:01:27 -07:00
|
|
|
}
|
|
|
|
|
Make moving of temporaries do the right thing, use it to optimize
This adds support for dropping cleanups for temporary values when they
are moved somewhere else. It then adds wraps most copy operations
(return, put in data structure, box, etc) in a way that will fall back
to a move when it is safe.
This saves a lot of taking/dropping, shaving over a megabyte off the
stage2/rustc binary size.
In some cases, most notably function returns, we could detect that the
returned value is a local variable, and can thus be safely moved even
though it is not a temporary. This will require putting some more
information in lvals.
I did not yet handle function arguments, since the logic for passing
them looked too convoluted to touch. I'll probably try that in the
near future, since it's bound to be a big win.
2011-07-07 13:36:12 +02:00
|
|
|
fn lookup_in_mod(&env e, &def m, &span sp, &ident name, namespace ns,
|
|
|
|
dir dr) -> option::t[def] {
|
2011-05-26 17:33:33 -07:00
|
|
|
auto defid = ast::def_id_of_def(m);
|
2011-07-26 14:06:02 +02:00
|
|
|
if (defid.crate != ast::local_crate) {
|
2011-05-26 17:33:33 -07:00
|
|
|
// examining a module in an external crate
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-26 14:06:02 +02:00
|
|
|
auto cached = e.ext_cache.find(rec(did=defid, ident=name, ns=ns));
|
2011-07-22 11:31:43 +02:00
|
|
|
if (!is_none(cached)) { ret cached; }
|
2011-07-13 16:44:39 -07:00
|
|
|
auto path = ~[name];
|
2011-07-26 14:06:02 +02:00
|
|
|
if (defid.node != -1) { path = e.ext_map.get(defid) + path; }
|
|
|
|
auto fnd = lookup_external(e, defid.crate, path, ns);
|
2011-07-22 11:31:43 +02:00
|
|
|
if (!is_none(fnd)) {
|
2011-07-26 14:06:02 +02:00
|
|
|
e.ext_cache.insert(rec(did=defid, ident=name, ns=ns),
|
|
|
|
option::get(fnd));
|
2011-05-26 17:33:33 -07:00
|
|
|
}
|
|
|
|
ret fnd;
|
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
alt (m) {
|
2011-05-26 17:33:33 -07:00
|
|
|
case (ast::def_mod(?defid)) {
|
2011-07-26 14:06:02 +02:00
|
|
|
ret lookup_in_local_mod(e, defid.node, sp, name, ns, dr);
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-26 17:33:33 -07:00
|
|
|
case (ast::def_native_mod(?defid)) {
|
2011-07-26 14:06:02 +02:00
|
|
|
ret lookup_in_local_native_mod(e, defid.node, sp, name, ns);
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
2010-10-18 14:37:30 -07:00
|
|
|
}
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
fn found_view_item(&env e, @ast::view_item vi, namespace ns) ->
|
|
|
|
option::t[def] {
|
2011-05-09 12:40:09 +02:00
|
|
|
alt (vi.node) {
|
2011-06-19 22:41:21 +02:00
|
|
|
case (ast::view_item_use(_, _, ?id)) {
|
2011-07-09 22:56:12 -07:00
|
|
|
auto cnum = cstore::get_use_stmt_cnum(e.cstore, id);
|
2011-07-26 14:06:02 +02:00
|
|
|
ret some(ast::def_mod(rec(crate=cnum, node=-1)));
|
2011-01-20 15:17:26 -08:00
|
|
|
}
|
2011-06-19 22:41:21 +02:00
|
|
|
case (ast::view_item_import(_, _, ?id)) {
|
|
|
|
ret lookup_import(e, local_def(id), ns);
|
2011-02-14 18:17:31 -08:00
|
|
|
}
|
2011-05-20 15:56:23 -07:00
|
|
|
case (ast::view_item_import_glob(_, ?defid)) {
|
2011-05-23 18:52:55 -07:00
|
|
|
ret none[def]; //will be handled in the fallback glob pass
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-05-20 15:56:23 -07:00
|
|
|
}
|
2011-01-20 15:17:26 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-13 10:51:36 +02:00
|
|
|
fn lookup_import(&env e, def_id defid, namespace ns) -> option::t[def] {
|
2011-07-26 14:06:02 +02:00
|
|
|
alt (e.imports.get(defid.node)) {
|
2011-05-13 10:51:36 +02:00
|
|
|
case (todo(?item, ?sc)) {
|
|
|
|
resolve_import(e, item, sc);
|
|
|
|
ret lookup_import(e, defid, ns);
|
|
|
|
}
|
2011-06-18 23:28:29 -07:00
|
|
|
case (resolving(?sp)) {
|
|
|
|
e.sess.span_err(sp, "cyclic import");
|
|
|
|
ret none;
|
|
|
|
}
|
2011-05-13 16:46:20 +02:00
|
|
|
case (resolved(?val, ?typ, ?md)) {
|
2011-06-15 11:19:50 -07:00
|
|
|
ret alt (ns) {
|
|
|
|
case (ns_value) { val }
|
|
|
|
case (ns_type) { typ }
|
|
|
|
case (ns_module) { md }
|
|
|
|
};
|
2011-05-13 10:51:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-19 22:41:21 +02:00
|
|
|
fn lookup_in_local_native_mod(&env e, node_id node_id, &span sp, &ident id,
|
2011-06-15 11:19:50 -07:00
|
|
|
namespace ns) -> option::t[def] {
|
2011-06-19 22:41:21 +02:00
|
|
|
ret lookup_in_local_mod(e, node_id, sp, id, ns, inside);
|
2011-05-25 10:10:30 -07:00
|
|
|
}
|
|
|
|
|
2011-06-19 22:41:21 +02:00
|
|
|
fn lookup_in_local_mod(&env e, node_id node_id, &span sp, &ident id,
|
2011-06-15 11:19:50 -07:00
|
|
|
namespace ns, dir dr) -> option::t[def] {
|
2011-06-19 22:41:21 +02:00
|
|
|
auto info = e.mod_map.get(node_id);
|
2011-06-10 12:02:57 +02:00
|
|
|
if (dr == outside && !ast::is_exported(id, option::get(info.m))) {
|
2011-06-15 11:19:50 -07:00
|
|
|
// if we're in a native mod, then dr==inside, so info.m is some _mod
|
|
|
|
|
|
|
|
ret none[def]; // name is not visible
|
|
|
|
|
2011-06-10 12:02:57 +02:00
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
alt (info.index.find(id)) {
|
2011-05-31 00:39:19 -04:00
|
|
|
case (none) { }
|
2011-06-10 12:02:57 +02:00
|
|
|
case (some(?lst_)) {
|
|
|
|
auto lst = lst_;
|
2011-05-23 18:52:55 -07:00
|
|
|
while (true) {
|
2011-06-10 12:02:57 +02:00
|
|
|
alt (lst) {
|
2011-05-31 00:39:19 -04:00
|
|
|
case (nil) { break; }
|
|
|
|
case (cons(?hd, ?tl)) {
|
2011-05-23 18:52:55 -07:00
|
|
|
auto found = lookup_in_mie(e, hd, ns);
|
2011-07-22 11:31:43 +02:00
|
|
|
if (!is_none(found)) { ret found; }
|
2011-05-23 18:52:55 -07:00
|
|
|
lst = *tl;
|
|
|
|
}
|
|
|
|
}
|
2011-05-13 13:34:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-06-22 15:41:39 -07:00
|
|
|
// not local or explicitly imported; try globs:
|
|
|
|
ret lookup_glob_in_mod(e, info, sp, id, ns, outside);
|
2011-05-23 18:52:55 -07:00
|
|
|
}
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
fn lookup_glob_in_mod(&env e, @indexed_mod info, &span sp, &ident id,
|
|
|
|
namespace wanted_ns, dir dr) -> option::t[def] {
|
|
|
|
fn per_ns(&env e, @indexed_mod info, &span sp, &ident id, namespace ns,
|
|
|
|
dir dr) -> option::t[def] {
|
2011-07-08 18:41:37 -07:00
|
|
|
|
|
|
|
fn lookup_in_mod_(&env e, &glob_imp_def def, &span sp,
|
|
|
|
&ident name, namespace ns,
|
|
|
|
dir dr) -> option::t[glob_imp_def] {
|
2011-07-26 14:06:02 +02:00
|
|
|
alt (lookup_in_mod(e, def.def, sp, name, ns, dr)) {
|
2011-07-08 18:41:37 -07:00
|
|
|
case (option::some(?d)) {
|
2011-07-26 14:06:02 +02:00
|
|
|
option::some(rec(def=d, item=def.item))
|
2011-07-08 18:41:37 -07:00
|
|
|
}
|
|
|
|
case (option::none) {
|
|
|
|
option::none
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
auto matches =
|
2011-07-13 16:44:39 -07:00
|
|
|
ivec::filter_map(bind lookup_in_mod_(e, _, sp, id, ns, dr),
|
|
|
|
{ info.glob_imports });
|
|
|
|
if (ivec::len(matches) == 0u) {
|
2011-07-26 14:06:02 +02:00
|
|
|
ret none;
|
2011-07-13 16:44:39 -07:00
|
|
|
} else if (ivec::len(matches) == 1u) {
|
2011-07-26 14:06:02 +02:00
|
|
|
ret some(matches.(0).def);
|
2011-05-26 17:33:33 -07:00
|
|
|
} else {
|
2011-07-08 18:41:37 -07:00
|
|
|
for (glob_imp_def match in matches) {
|
2011-07-26 14:06:02 +02:00
|
|
|
auto sp = match.item.span;
|
2011-07-08 18:41:37 -07:00
|
|
|
e.sess.span_note(sp, #fmt("'%s' is imported here", id));
|
2011-05-26 17:33:33 -07:00
|
|
|
}
|
2011-06-18 22:41:20 -07:00
|
|
|
e.sess.span_fatal(sp,
|
2011-06-15 11:19:50 -07:00
|
|
|
"'" + id + "' is glob-imported from" +
|
|
|
|
" multiple different modules.");
|
2011-05-26 17:33:33 -07:00
|
|
|
}
|
2011-05-23 18:52:55 -07:00
|
|
|
}
|
2011-05-26 17:33:33 -07:00
|
|
|
// since we don't know what names we have in advance,
|
|
|
|
// absence takes the place of todo()
|
2011-06-15 11:19:50 -07:00
|
|
|
|
|
|
|
if (!info.glob_imported_names.contains_key(id)) {
|
2011-05-26 17:33:33 -07:00
|
|
|
info.glob_imported_names.insert(id, resolving(sp));
|
|
|
|
auto val = per_ns(e, info, sp, id, ns_value, dr);
|
|
|
|
auto typ = per_ns(e, info, sp, id, ns_type, dr);
|
2011-06-15 11:19:50 -07:00
|
|
|
auto md = per_ns(e, info, sp, id, ns_module, dr);
|
2011-05-26 17:33:33 -07:00
|
|
|
info.glob_imported_names.insert(id, resolved(val, typ, md));
|
|
|
|
}
|
|
|
|
alt (info.glob_imported_names.get(id)) {
|
2011-06-15 11:19:50 -07:00
|
|
|
case (todo(_, _)) { e.sess.bug("Shouldn't've put a todo in."); }
|
2011-05-26 17:33:33 -07:00
|
|
|
case (resolving(?sp)) {
|
|
|
|
ret none[def]; //circularity is okay in import globs
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-05-26 17:33:33 -07:00
|
|
|
}
|
|
|
|
case (resolved(?val, ?typ, ?md)) {
|
2011-06-15 11:19:50 -07:00
|
|
|
ret alt (wanted_ns) {
|
|
|
|
case (ns_value) { val }
|
|
|
|
case (ns_type) { typ }
|
|
|
|
case (ns_module) { md }
|
|
|
|
};
|
2011-05-25 11:55:48 -07:00
|
|
|
}
|
2011-05-23 18:52:55 -07:00
|
|
|
}
|
2011-05-13 13:34:59 +02:00
|
|
|
}
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
fn lookup_in_mie(&env e, &mod_index_entry mie, namespace ns) ->
|
|
|
|
option::t[def] {
|
2011-05-13 13:34:59 +02:00
|
|
|
alt (mie) {
|
2011-05-11 16:30:48 +02:00
|
|
|
case (mie_view_item(?view_item)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
ret found_view_item(e, view_item, ns);
|
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
case (mie_item(?item)) { ret found_def_item(item, ns); }
|
2011-05-11 16:30:48 +02:00
|
|
|
case (mie_tag_variant(?item, ?variant_idx)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
alt (item.node) {
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_tag(?variants, _)) {
|
2011-05-09 12:40:09 +02:00
|
|
|
if (ns == ns_value) {
|
|
|
|
auto vid = variants.(variant_idx).node.id;
|
2011-06-19 22:41:21 +02:00
|
|
|
ret some(ast::def_variant(local_def(item.id),
|
|
|
|
local_def(vid)));
|
2011-06-15 11:19:50 -07:00
|
|
|
} else { ret none[def]; }
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
2011-05-13 13:34:59 +02:00
|
|
|
}
|
2011-05-19 11:37:17 -07:00
|
|
|
case (mie_native_item(?native_item)) {
|
|
|
|
alt (native_item.node) {
|
2011-06-21 23:01:08 +02:00
|
|
|
case (ast::native_item_ty) {
|
2011-06-19 22:41:21 +02:00
|
|
|
if (ns == ns_type) {
|
2011-06-21 23:01:08 +02:00
|
|
|
ret some(ast::def_native_ty
|
|
|
|
(local_def(native_item.id)));
|
2011-06-19 22:41:21 +02:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-06-21 23:01:08 +02:00
|
|
|
case (ast::native_item_fn(_, _, _)) {
|
2011-06-19 22:41:21 +02:00
|
|
|
if (ns == ns_value) {
|
2011-06-21 23:01:08 +02:00
|
|
|
ret some(ast::def_native_fn
|
|
|
|
(local_def(native_item.id)));
|
2011-06-19 22:41:21 +02:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
case (_) { }
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
|
|
|
ret none[def];
|
2011-01-18 15:23:11 -05:00
|
|
|
}
|
|
|
|
|
2011-05-19 11:37:17 -07:00
|
|
|
|
2011-05-11 16:30:48 +02:00
|
|
|
// Module indexing
|
2011-06-15 11:19:50 -07:00
|
|
|
fn add_to_index(&hashmap[ident, list[mod_index_entry]] index, &ident id,
|
2011-05-20 15:56:23 -07:00
|
|
|
&mod_index_entry ent) {
|
2011-05-13 13:34:59 +02:00
|
|
|
alt (index.find(id)) {
|
2011-06-15 11:19:50 -07:00
|
|
|
case (none) { index.insert(id, cons(ent, @nil[mod_index_entry])); }
|
|
|
|
case (some(?prev)) { index.insert(id, cons(ent, @prev)); }
|
2011-05-13 13:34:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-12 17:24:54 +02:00
|
|
|
fn index_mod(&ast::_mod md) -> mod_index {
|
2011-05-13 13:34:59 +02:00
|
|
|
auto index = new_str_hash[list[mod_index_entry]]();
|
2011-05-12 17:24:54 +02:00
|
|
|
for (@ast::view_item it in md.view_items) {
|
2011-05-11 16:30:48 +02:00
|
|
|
alt (it.node) {
|
2011-07-27 10:01:21 +02:00
|
|
|
ast::view_item_import(?ident, _, _) |
|
|
|
|
ast::view_item_use(?ident, _, _) {
|
|
|
|
add_to_index(index, ident, mie_view_item(it));
|
|
|
|
}
|
|
|
|
//globbed imports have to be resolved lazily.
|
|
|
|
ast::view_item_import_glob(_, _) | ast::view_item_export(_, _) {}
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
for (@ast::item it in md.items) {
|
2011-05-11 16:30:48 +02:00
|
|
|
alt (it.node) {
|
2011-07-11 21:23:40 +02:00
|
|
|
ast::item_const(_, _) | ast::item_fn(_, _) | ast::item_mod(_) |
|
|
|
|
ast::item_native_mod(_) | ast::item_ty(_, _) |
|
|
|
|
ast::item_res(_, _, _, _) | ast::item_obj(_, _, _) {
|
2011-06-24 18:10:40 +02:00
|
|
|
add_to_index(index, it.ident, mie_item(it));
|
|
|
|
}
|
2011-07-11 21:23:40 +02:00
|
|
|
ast::item_tag(?variants, _) {
|
2011-06-16 11:53:06 +02:00
|
|
|
add_to_index(index, it.ident, mie_item(it));
|
2011-05-11 16:30:48 +02:00
|
|
|
let uint variant_idx = 0u;
|
2011-05-12 17:24:54 +02:00
|
|
|
for (ast::variant v in variants) {
|
2011-05-13 13:34:59 +02:00
|
|
|
add_to_index(index, v.node.name,
|
2011-06-15 11:19:50 -07:00
|
|
|
mie_tag_variant(it, variant_idx));
|
2011-05-11 16:30:48 +02:00
|
|
|
variant_idx += 1u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ret index;
|
|
|
|
}
|
|
|
|
|
2011-05-19 11:37:17 -07:00
|
|
|
fn index_nmod(&ast::native_mod md) -> mod_index {
|
|
|
|
auto index = new_str_hash[list[mod_index_entry]]();
|
2011-05-12 17:24:54 +02:00
|
|
|
for (@ast::view_item it in md.view_items) {
|
2011-05-11 16:30:48 +02:00
|
|
|
alt (it.node) {
|
2011-07-27 10:01:21 +02:00
|
|
|
ast::view_item_use(?ident, _, _) |
|
|
|
|
ast::view_item_import(?ident, _, _) {
|
|
|
|
add_to_index(index, ident, mie_view_item(it));
|
|
|
|
}
|
|
|
|
ast::view_item_import_glob(_, _) | ast::view_item_export(_, _) {}
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
|
|
|
}
|
2011-05-12 17:24:54 +02:00
|
|
|
for (@ast::native_item it in md.items) {
|
2011-06-21 23:01:08 +02:00
|
|
|
add_to_index(index, it.ident, mie_native_item(it));
|
2011-05-11 16:30:48 +02:00
|
|
|
}
|
|
|
|
ret index;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
// External lookups
|
2011-05-13 16:46:20 +02:00
|
|
|
fn ns_for_def(def d) -> namespace {
|
2011-05-09 12:40:09 +02:00
|
|
|
ret alt (d) {
|
2011-06-20 17:29:54 -07:00
|
|
|
case (ast::def_fn(?id, _)) { ns_value }
|
2011-06-15 11:19:50 -07:00
|
|
|
case (ast::def_obj_field(?id)) { ns_value }
|
|
|
|
case (ast::def_mod(?id)) { ns_module }
|
|
|
|
case (ast::def_native_mod(?id)) { ns_module }
|
|
|
|
case (ast::def_const(?id)) { ns_value }
|
|
|
|
case (ast::def_arg(?id)) { ns_value }
|
|
|
|
case (ast::def_local(?id)) { ns_value }
|
|
|
|
case (ast::def_variant(_, ?id)) { ns_value }
|
|
|
|
case (ast::def_ty(?id)) { ns_type }
|
|
|
|
case (ast::def_binding(?id)) { ns_type }
|
|
|
|
case (ast::def_use(?id)) { ns_module }
|
|
|
|
case (ast::def_native_ty(?id)) { ns_type }
|
|
|
|
case (ast::def_native_fn(?id)) { ns_value }
|
|
|
|
};
|
2010-10-07 18:34:22 -07:00
|
|
|
}
|
|
|
|
|
2011-07-13 16:44:39 -07:00
|
|
|
fn lookup_external(&env e, int cnum, &ident[] ids, namespace ns) ->
|
2011-06-15 11:19:50 -07:00
|
|
|
option::t[def] {
|
2011-07-14 17:26:10 -07:00
|
|
|
for (def d in csearch::lookup_defs(e.sess.get_cstore(), cnum, ids)) {
|
2011-05-12 17:24:54 +02:00
|
|
|
e.ext_map.insert(ast::def_id_of_def(d), ids);
|
2011-05-13 16:46:20 +02:00
|
|
|
if (ns == ns_for_def(d)) { ret some(d); }
|
2011-05-09 12:40:09 +02:00
|
|
|
}
|
2011-05-13 15:17:24 +02:00
|
|
|
ret none[def];
|
2011-05-11 12:21:09 +02:00
|
|
|
}
|
2011-05-09 12:40:09 +02:00
|
|
|
|
2011-05-18 22:23:19 +02:00
|
|
|
|
2011-06-15 11:19:50 -07:00
|
|
|
// Collision detection
|
2011-05-18 22:23:19 +02:00
|
|
|
fn check_for_collisions(&@env e, &ast::crate c) {
|
2011-05-19 21:46:51 +02:00
|
|
|
// Module indices make checking those relatively simple -- just check each
|
|
|
|
// name for multiple entities in the same namespace.
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-07-26 14:06:02 +02:00
|
|
|
for each (@rec(ast::node_id key, @indexed_mod val) m
|
|
|
|
in e.mod_map.items()) {
|
|
|
|
for each (@rec(ident key, list[mod_index_entry] val) name
|
|
|
|
in m.val.index.items()) {
|
|
|
|
check_mod_name(*e, name.key, name.val);
|
2011-05-18 22:23:19 +02:00
|
|
|
}
|
|
|
|
}
|
2011-05-19 21:46:51 +02:00
|
|
|
// Other scopes have to be checked the hard way.
|
2011-06-15 11:19:50 -07:00
|
|
|
|
|
|
|
auto v =
|
|
|
|
@rec(visit_item=bind check_item(e, _, _, _),
|
|
|
|
visit_block=bind check_block(e, _, _, _),
|
2011-07-26 15:32:16 +02:00
|
|
|
visit_arm=bind check_arm(e, _, _, _),
|
|
|
|
visit_expr=bind check_expr(e, _, _, _),
|
|
|
|
visit_ty=bind check_ty(e, _, _, _)
|
2011-06-15 11:19:50 -07:00
|
|
|
with *visit::default_visitor());
|
2011-07-01 14:05:54 +02:00
|
|
|
visit::visit_crate(c, (), visit::mk_vt(v));
|
2011-05-18 22:23:19 +02:00
|
|
|
}
|
|
|
|
|
2011-06-10 12:02:57 +02:00
|
|
|
fn check_mod_name(&env e, &ident name, list[mod_index_entry] entries) {
|
2011-06-15 11:19:50 -07:00
|
|
|
auto saw_mod = false;
|
|
|
|
auto saw_type = false;
|
|
|
|
auto saw_value = false;
|
2011-05-18 22:23:19 +02:00
|
|
|
fn dup(&env e, &span sp, &str word, &ident name) {
|
2011-06-18 22:41:20 -07:00
|
|
|
e.sess.span_fatal(sp, "duplicate definition of " + word + name);
|
2011-05-18 22:23:19 +02:00
|
|
|
}
|
|
|
|
while (true) {
|
2011-06-10 12:02:57 +02:00
|
|
|
alt (entries) {
|
2011-05-31 00:39:19 -04:00
|
|
|
case (cons(?entry, ?rest)) {
|
2011-07-22 11:31:43 +02:00
|
|
|
if (!is_none(lookup_in_mie(e, entry, ns_value))) {
|
2011-06-15 11:19:50 -07:00
|
|
|
if (saw_value) {
|
|
|
|
dup(e, mie_span(entry), "", name);
|
|
|
|
} else { saw_value = true; }
|
2011-05-18 22:23:19 +02:00
|
|
|
}
|
2011-07-22 11:31:43 +02:00
|
|
|
if (!is_none(lookup_in_mie(e, entry, ns_type))) {
|
2011-06-15 11:19:50 -07:00
|
|
|
if (saw_type) {
|
|
|
|
dup(e, mie_span(entry), "type ", name);
|
|
|
|
} else { saw_type = true; }
|
2011-05-18 22:23:19 +02:00
|
|
|
}
|
2011-07-22 11:31:43 +02:00
|
|
|
if (!is_none(lookup_in_mie(e, entry, ns_module))) {
|
2011-06-15 11:19:50 -07:00
|
|
|
if (saw_mod) {
|
|
|
|
dup(e, mie_span(entry), "module ", name);
|
|
|
|
} else { saw_mod = true; }
|
2011-05-18 22:23:19 +02:00
|
|
|
}
|
|
|
|
entries = *rest;
|
|
|
|
}
|
2011-05-31 00:39:19 -04:00
|
|
|
case (nil) { break; }
|
2011-05-18 22:23:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn mie_span(&mod_index_entry mie) -> span {
|
2011-07-11 21:23:40 +02:00
|
|
|
ret alt (mie) {
|
|
|
|
mie_view_item(?item) { item.span }
|
|
|
|
mie_item(?item) { item.span }
|
|
|
|
mie_tag_variant(?item, _) { item.span }
|
|
|
|
mie_native_item(?item) { item.span }
|
|
|
|
};
|
2011-05-18 22:23:19 +02:00
|
|
|
}
|
|
|
|
|
2011-07-26 15:32:16 +02:00
|
|
|
fn check_item(&@env e, &@ast::item i, &() x, &vt[()] v) {
|
2011-06-09 15:50:26 +02:00
|
|
|
visit::visit_item(i, x, v);
|
2011-05-19 21:46:51 +02:00
|
|
|
alt (i.node) {
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_fn(?f, ?ty_params)) {
|
2011-05-19 21:46:51 +02:00
|
|
|
check_fn(*e, i.span, f);
|
2011-07-26 15:32:16 +02:00
|
|
|
ensure_unique(*e, i.span, ty_params, ident_id,
|
2011-07-06 19:00:00 -07:00
|
|
|
"type parameter");
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_obj(?ob, ?ty_params, _)) {
|
2011-06-15 11:19:50 -07:00
|
|
|
fn field_name(&ast::obj_field field) -> ident { ret field.ident; }
|
2011-07-26 15:32:16 +02:00
|
|
|
ensure_unique(*e, i.span, ob.fields, field_name,
|
2011-07-06 19:00:00 -07:00
|
|
|
"object field");
|
2011-05-19 21:46:51 +02:00
|
|
|
for (@ast::method m in ob.methods) {
|
|
|
|
check_fn(*e, m.span, m.node.meth);
|
|
|
|
}
|
2011-07-26 15:32:16 +02:00
|
|
|
ensure_unique(*e, i.span, ty_params, ident_id,
|
2011-07-06 19:00:00 -07:00
|
|
|
"type parameter");
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
2011-06-16 11:53:06 +02:00
|
|
|
case (ast::item_tag(_, ?ty_params)) {
|
2011-07-26 15:32:16 +02:00
|
|
|
ensure_unique(*e, i.span, ty_params, ident_id,
|
2011-07-06 19:00:00 -07:00
|
|
|
"type parameter");
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
case (_) { }
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-26 15:32:16 +02:00
|
|
|
fn check_arm(&@env e, &ast::arm a, &() x, &vt[()] v) {
|
2011-06-09 15:50:26 +02:00
|
|
|
visit::visit_arm(a, x, v);
|
2011-05-19 21:46:51 +02:00
|
|
|
fn walk_pat(checker ch, &@ast::pat p) {
|
|
|
|
alt (p.node) {
|
2011-07-04 21:53:33 +02:00
|
|
|
case (ast::pat_bind(?name)) { add_name(ch, p.span, name); }
|
|
|
|
case (ast::pat_tag(_, ?children)) {
|
2011-06-15 11:19:50 -07:00
|
|
|
for (@ast::pat child in children) { walk_pat(ch, child); }
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
2011-07-11 14:13:20 +02:00
|
|
|
case (ast::pat_rec(?fields, _)) {
|
|
|
|
for (ast::field_pat f in fields) { walk_pat(ch, f.pat); }
|
|
|
|
}
|
2011-07-13 10:50:16 +02:00
|
|
|
case (ast::pat_box(?inner)) { walk_pat(ch, inner); }
|
2011-06-15 11:19:50 -07:00
|
|
|
case (_) { }
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
|
|
|
}
|
2011-07-08 16:27:55 +02:00
|
|
|
auto ch0 = checker(*e, "binding");
|
|
|
|
walk_pat(ch0, a.pats.(0));
|
|
|
|
auto seen0 = ch0.seen;
|
|
|
|
auto i = ivec::len(a.pats);
|
|
|
|
while (i > 1u) {
|
|
|
|
i -= 1u;
|
|
|
|
auto ch = checker(*e, "binding");
|
|
|
|
walk_pat(ch, a.pats.(i));
|
|
|
|
// Ensure the bindings introduced in this pattern are the same as in
|
|
|
|
// the first pattern.
|
2011-07-13 16:44:39 -07:00
|
|
|
if (ivec::len(ch.seen) != ivec::len(seen0)) {
|
2011-07-08 16:27:55 +02:00
|
|
|
e.sess.span_err(a.pats.(i).span,
|
|
|
|
"inconsistent number of bindings");
|
|
|
|
} else {
|
|
|
|
for (ident name in ch.seen) {
|
2011-07-22 11:31:43 +02:00
|
|
|
if (is_none(ivec::find(bind str::eq(name, _), seen0))) {
|
2011-07-08 16:27:55 +02:00
|
|
|
// Fight the alias checker
|
|
|
|
auto name_ = name;
|
|
|
|
e.sess.span_err
|
2011-07-13 15:44:09 -07:00
|
|
|
(a.pats.(i).span, "binding " + name_ +
|
2011-07-08 16:27:55 +02:00
|
|
|
" does not occur in first pattern");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
|
|
|
|
2011-07-26 15:32:16 +02:00
|
|
|
fn check_block(&@env e, &ast::blk b, &() x, &vt[()] v) {
|
2011-06-09 15:50:26 +02:00
|
|
|
visit::visit_block(b, x, v);
|
2011-05-19 21:46:51 +02:00
|
|
|
auto values = checker(*e, "value");
|
|
|
|
auto types = checker(*e, "type");
|
|
|
|
auto mods = checker(*e, "module");
|
|
|
|
for (@ast::stmt st in b.node.stmts) {
|
|
|
|
alt (st.node) {
|
2011-06-15 11:19:50 -07:00
|
|
|
case (ast::stmt_decl(?d, _)) {
|
2011-05-19 21:46:51 +02:00
|
|
|
alt (d.node) {
|
2011-07-22 17:19:06 +02:00
|
|
|
ast::decl_local(?locs) {
|
|
|
|
for (@ast::local loc in locs) {
|
|
|
|
add_name(values, d.span, loc.node.ident);
|
|
|
|
}
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
2011-07-11 21:23:40 +02:00
|
|
|
ast::decl_item(?it) {
|
2011-05-19 21:46:51 +02:00
|
|
|
alt (it.node) {
|
2011-07-11 21:23:40 +02:00
|
|
|
ast::item_tag(?variants, _) {
|
2011-06-16 11:53:06 +02:00
|
|
|
add_name(types, it.span, it.ident);
|
2011-05-19 21:46:51 +02:00
|
|
|
for (ast::variant v in variants) {
|
|
|
|
add_name(values, v.span, v.node.name);
|
|
|
|
}
|
|
|
|
}
|
2011-07-11 21:23:40 +02:00
|
|
|
ast::item_mod(_) | ast::item_native_mod(_) {
|
2011-06-16 11:53:06 +02:00
|
|
|
add_name(mods, it.span, it.ident);
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
2011-07-11 21:23:40 +02:00
|
|
|
ast::item_const(_, _) | ast::item_fn(_, _) {
|
|
|
|
add_name(values, it.span, it.ident);
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
2011-07-11 21:23:40 +02:00
|
|
|
ast::item_ty(_, _) {
|
2011-06-24 18:10:40 +02:00
|
|
|
add_name(types, it.span, it.ident);
|
|
|
|
}
|
2011-07-11 21:23:40 +02:00
|
|
|
ast::item_res(_, _, _, _) |
|
|
|
|
ast::item_obj(_, _, _) {
|
2011-06-16 11:53:06 +02:00
|
|
|
add_name(types, it.span, it.ident);
|
|
|
|
add_name(values, it.span, it.ident);
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
2011-07-11 21:23:40 +02:00
|
|
|
_ { }
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-15 11:19:50 -07:00
|
|
|
case (_) { }
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check_fn(&env e, &span sp, &ast::_fn f) {
|
2011-06-15 11:19:50 -07:00
|
|
|
fn arg_name(&ast::arg a) -> ident { ret a.ident; }
|
2011-07-26 15:32:16 +02:00
|
|
|
ensure_unique(e, sp, f.decl.inputs, arg_name, "argument");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check_expr(&@env e, &@ast::expr ex, &() x, &vt[()] v) {
|
|
|
|
alt ex.node {
|
|
|
|
ast::expr_rec(?fields, _) {
|
|
|
|
fn field_name(&ast::field f) -> ident { ret f.node.ident; }
|
2011-07-26 15:50:15 +02:00
|
|
|
ensure_unique(*e, ex.span, fields, field_name, "field");
|
2011-07-26 15:32:16 +02:00
|
|
|
}
|
|
|
|
_ {}
|
|
|
|
}
|
|
|
|
visit::visit_expr(ex, x, v);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check_ty(&@env e, &@ast::ty ty, &() x, &vt[()] v) {
|
|
|
|
alt ty.node {
|
|
|
|
ast::ty_rec(?fields) {
|
|
|
|
fn field_name(&ast::ty_field f) -> ident { ret f.node.ident; }
|
2011-07-26 15:50:15 +02:00
|
|
|
ensure_unique(*e, ty.span, fields, field_name, "field");
|
2011-07-26 15:32:16 +02:00
|
|
|
}
|
|
|
|
_ {}
|
|
|
|
}
|
|
|
|
visit::visit_ty(ty, x, v);
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
|
|
|
|
2011-07-13 16:44:39 -07:00
|
|
|
type checker = @rec(mutable ident[] seen, str kind, session sess);
|
2011-06-15 11:19:50 -07:00
|
|
|
|
2011-05-19 21:46:51 +02:00
|
|
|
fn checker(&env e, str kind) -> checker {
|
2011-07-13 16:44:39 -07:00
|
|
|
let ident[] seen = ~[];
|
2011-05-19 21:46:51 +02:00
|
|
|
ret @rec(mutable seen=seen, kind=kind, sess=e.sess);
|
|
|
|
}
|
|
|
|
|
2011-06-20 08:14:24 +02:00
|
|
|
fn add_name(&checker ch, &span sp, &ident name) {
|
2011-05-19 21:46:51 +02:00
|
|
|
for (ident s in ch.seen) {
|
2011-06-20 08:14:24 +02:00
|
|
|
if (str::eq(s, name)) {
|
|
|
|
ch.sess.span_fatal(sp, "duplicate " + ch.kind + " name: " + name);
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
|
|
|
}
|
2011-07-13 16:44:39 -07:00
|
|
|
ch.seen += ~[name];
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn ident_id(&ident i) -> ident { ret i; }
|
|
|
|
|
2011-07-13 16:44:39 -07:00
|
|
|
fn ensure_unique[T](&env e, &span sp, &T[] elts, fn(&T) -> ident id,
|
2011-05-19 21:46:51 +02:00
|
|
|
&str kind) {
|
|
|
|
auto ch = checker(e, kind);
|
2011-06-15 11:19:50 -07:00
|
|
|
for (T elt in elts) { add_name(ch, sp, id(elt)); }
|
2011-05-19 21:46:51 +02:00
|
|
|
}
|
2011-07-06 19:00:00 -07:00
|
|
|
|
2010-10-07 18:34:22 -07:00
|
|
|
// Local Variables:
|
|
|
|
// mode: rust
|
|
|
|
// fill-column: 78;
|
|
|
|
// indent-tabs-mode: nil
|
|
|
|
// c-basic-offset: 4
|
|
|
|
// buffer-file-coding-system: utf-8-unix
|
2011-03-25 15:07:27 -07:00
|
|
|
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
|
2010-10-07 18:34:22 -07:00
|
|
|
// End:
|