parent
d5af61d679
commit
888bc80025
@ -162,7 +162,7 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
|
||||
bind middle::ast_map::map_crate(*crate));
|
||||
time(time_passes, "external crate/lib resolution",
|
||||
bind creader::read_crates(sess, *crate));
|
||||
let {def_map: def_map, ext_map: ext_map, exp_map: exp_map} =
|
||||
let {def_map, ext_map, exp_map, impl_map} =
|
||||
time(time_passes, "resolution",
|
||||
bind resolve::resolve_crate(sess, ast_map, crate));
|
||||
let freevars =
|
||||
@ -171,7 +171,8 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
|
||||
time(time_passes, "const checking",
|
||||
bind middle::check_const::check_crate(sess, crate));
|
||||
let ty_cx = ty::mk_ctxt(sess, def_map, ext_map, ast_map, freevars);
|
||||
time(time_passes, "typechecking", bind typeck::check_crate(ty_cx, crate));
|
||||
time(time_passes, "typechecking",
|
||||
bind typeck::check_crate(ty_cx, impl_map, crate));
|
||||
time(time_passes, "block-use checking",
|
||||
bind middle::block_use::check_crate(ty_cx, crate));
|
||||
time(time_passes, "function usage",
|
||||
@ -267,11 +268,11 @@ fn pretty_print_input(sess: session::session, cfg: ast::crate_cfg, input: str,
|
||||
ppm_typed. {
|
||||
crate = syntax::ext::expand::expand_crate(sess, crate);
|
||||
let amap = middle::ast_map::map_crate(*crate);
|
||||
let {def_map: def_map, ext_map: ext_map, exp_map: _exp_map} =
|
||||
let {def_map, ext_map, impl_map, _} =
|
||||
resolve::resolve_crate(sess, amap, crate);
|
||||
let freevars = freevars::annotate_freevars(def_map, crate);
|
||||
let ty_cx = ty::mk_ctxt(sess, def_map, ext_map, amap, freevars);
|
||||
typeck::check_crate(ty_cx, crate);
|
||||
typeck::check_crate(ty_cx, impl_map, crate);
|
||||
ann = {pre: ann_paren_for_expr, post: bind ann_typed_post(ty_cx, _)};
|
||||
}
|
||||
ppm_identified. {
|
||||
|
@ -532,7 +532,7 @@ fn ty_can_unsafely_include(cx: ctx, needle: unsafe_ty, haystack: ty::t,
|
||||
fn def_is_local(d: ast::def, objfields_count: bool) -> bool {
|
||||
ret alt d {
|
||||
ast::def_local(_, _) | ast::def_arg(_, _) | ast::def_binding(_) |
|
||||
ast::def_upvar(_, _, _) {
|
||||
ast::def_upvar(_, _, _) | ast::def_self(_) {
|
||||
true
|
||||
}
|
||||
ast::def_obj_field(_, _) { objfields_count }
|
||||
|
@ -264,6 +264,7 @@ fn is_immutable_def(def: def) -> option::t<str> {
|
||||
def_arg(_, by_ref.) | def_arg(_, by_val.) |
|
||||
def_arg(_, mode_infer.) { some("argument") }
|
||||
def_obj_field(_, imm.) { some("immutable object field") }
|
||||
def_self(_) { some("self argument") }
|
||||
def_upvar(_, inner, mut) {
|
||||
if !mut { some("upvar") } else { is_immutable_def(*inner) }
|
||||
}
|
||||
|
@ -19,9 +19,7 @@ import option::{some, none, is_none, is_some};
|
||||
import syntax::print::pprust::*;
|
||||
|
||||
export resolve_crate;
|
||||
export def_map;
|
||||
export ext_map;
|
||||
export exp_map;
|
||||
export def_map, ext_map, exp_map, impl_map;
|
||||
|
||||
// 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,
|
||||
@ -45,14 +43,23 @@ type scopes = list<scope>;
|
||||
|
||||
tag import_state {
|
||||
todo(ast::node_id, ast::ident, @[ast::ident], codemap::span, scopes);
|
||||
is_glob(@[ast::ident], scopes, codemap::span);
|
||||
resolving(span);
|
||||
resolved(option::t<def>, /* value */
|
||||
option::t<def>, /* type */
|
||||
option::t<def>, /* module */
|
||||
@[def_id],
|
||||
/* used for reporting unused import warning */
|
||||
ast::ident, codemap::span);
|
||||
}
|
||||
|
||||
tag glob_import_state {
|
||||
glob_resolving(span);
|
||||
glob_resolved(option::t<def>, /* value */
|
||||
option::t<def>, /* type */
|
||||
option::t<def>); /* module */
|
||||
}
|
||||
|
||||
type ext_hash = hashmap<{did: def_id, ident: str, ns: namespace}, def>;
|
||||
|
||||
fn new_ext_hash() -> ext_hash {
|
||||
@ -89,7 +96,7 @@ type indexed_mod = {
|
||||
m: option::t<ast::_mod>,
|
||||
index: mod_index,
|
||||
mutable glob_imports: [glob_imp_def],
|
||||
glob_imported_names: hashmap<str, import_state>,
|
||||
glob_imported_names: hashmap<str, glob_import_state>,
|
||||
path: str
|
||||
};
|
||||
|
||||
@ -99,6 +106,7 @@ type indexed_mod = {
|
||||
type def_map = hashmap<node_id, def>;
|
||||
type ext_map = hashmap<def_id, [ident]>;
|
||||
type exp_map = hashmap<str, def>;
|
||||
type impl_map = hashmap<node_id, iscopes>;
|
||||
|
||||
type env =
|
||||
{cstore: cstore::cstore,
|
||||
@ -109,6 +117,7 @@ type env =
|
||||
mod_map: hashmap<ast::node_id, @indexed_mod>,
|
||||
block_map: hashmap<ast::node_id, [glob_imp_def]>,
|
||||
ext_map: ext_map,
|
||||
impl_map: impl_map,
|
||||
ext_cache: ext_hash,
|
||||
used_imports: {mutable track: bool,
|
||||
mutable data: [ast::node_id]},
|
||||
@ -124,7 +133,8 @@ tag dir { inside; outside; }
|
||||
tag namespace { ns_value; ns_type; ns_module; }
|
||||
|
||||
fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
|
||||
{def_map: def_map, ext_map: ext_map, exp_map: exp_map} {
|
||||
{def_map: def_map, ext_map: ext_map,
|
||||
exp_map: exp_map, impl_map: impl_map} {
|
||||
let e =
|
||||
@{cstore: sess.get_cstore(),
|
||||
def_map: new_int_hash(),
|
||||
@ -134,6 +144,7 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
|
||||
mod_map: new_int_hash(),
|
||||
block_map: new_int_hash(),
|
||||
ext_map: new_def_hash(),
|
||||
impl_map: new_int_hash(),
|
||||
ext_cache: new_ext_hash(),
|
||||
used_imports: {mutable track: false, mutable data: []},
|
||||
mutable reported: [],
|
||||
@ -144,10 +155,12 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) ->
|
||||
check_for_collisions(e, *crate);
|
||||
check_exports(e);
|
||||
resolve_names(e, crate);
|
||||
resolve_impls(e, crate);
|
||||
if sess.get_opts().warn_unused_imports {
|
||||
check_unused_imports(e);
|
||||
}
|
||||
ret {def_map: e.def_map, ext_map: e.ext_map, exp_map: e.exp_map};
|
||||
ret {def_map: e.def_map, ext_map: e.ext_map,
|
||||
exp_map: e.exp_map, impl_map: e.impl_map};
|
||||
}
|
||||
|
||||
// Locate all modules and imports and index them, so that the next passes can
|
||||
@ -166,7 +179,7 @@ fn map_crate(e: @env, c: @ast::crate) {
|
||||
@{m: some(c.node.module),
|
||||
index: index_mod(c.node.module),
|
||||
mutable glob_imports: [],
|
||||
glob_imported_names: new_str_hash::<import_state>(),
|
||||
glob_imported_names: new_str_hash(),
|
||||
path: ""});
|
||||
fn index_vi(e: @env, i: @ast::view_item, sc: scopes, _v: vt<scopes>) {
|
||||
alt i.node {
|
||||
@ -181,6 +194,9 @@ fn map_crate(e: @env, c: @ast::crate) {
|
||||
ident.span, sc));
|
||||
}
|
||||
}
|
||||
ast::view_item_import_glob(pth, id) {
|
||||
e.imports.insert(id, is_glob(pth, sc, i.span));
|
||||
}
|
||||
_ { }
|
||||
}
|
||||
}
|
||||
@ -198,21 +214,19 @@ fn map_crate(e: @env, c: @ast::crate) {
|
||||
visit_item_with_scope(i, sc, v);
|
||||
alt i.node {
|
||||
ast::item_mod(md) {
|
||||
let s = new_str_hash::<import_state>();
|
||||
e.mod_map.insert(i.id,
|
||||
@{m: some(md),
|
||||
index: index_mod(md),
|
||||
mutable glob_imports: [],
|
||||
glob_imported_names: s,
|
||||
glob_imported_names: new_str_hash(),
|
||||
path: path_from_scope(sc, i.ident)});
|
||||
}
|
||||
ast::item_native_mod(nmd) {
|
||||
let s = new_str_hash::<import_state>();
|
||||
e.mod_map.insert(i.id,
|
||||
@{m: none::<ast::_mod>,
|
||||
index: index_nmod(nmd),
|
||||
mutable glob_imports: [],
|
||||
glob_imported_names: s,
|
||||
glob_imported_names: new_str_hash(),
|
||||
path: path_from_scope(sc, i.ident)});
|
||||
}
|
||||
_ { }
|
||||
@ -233,7 +247,7 @@ fn map_crate(e: @env, c: @ast::crate) {
|
||||
ast::view_item_import_glob(path, _) {
|
||||
let imp = follow_import(*e, sc, *path, vi.span);
|
||||
if option::is_some(imp) {
|
||||
let glob = {def: option::get(imp), item: vi};;
|
||||
let glob = {def: option::get(imp), item: vi};
|
||||
alt list::head(sc) {
|
||||
scope_item(i) {
|
||||
e.mod_map.get(i.id).glob_imports += [glob];
|
||||
@ -262,7 +276,7 @@ fn resolve_imports(e: env) {
|
||||
todo(node_id, name, path, span, scopes) {
|
||||
resolve_import(e, local_def(node_id), name, *path, span, scopes);
|
||||
}
|
||||
resolved(_, _, _, _, _) { }
|
||||
resolved(_, _, _, _, _, _) | is_glob(_, _, _) { }
|
||||
}
|
||||
};
|
||||
e.used_imports.track = false;
|
||||
@ -272,7 +286,7 @@ fn resolve_imports(e: env) {
|
||||
fn check_unused_imports(e: @env) {
|
||||
e.imports.items {|k, v|
|
||||
alt v {
|
||||
resolved(val, ty, md, name, sp) {
|
||||
resolved(_, _, _, _, name, sp) {
|
||||
if !vec::member(k, e.used_imports.data) {
|
||||
e.sess.span_warn(sp, "unused import " + name);
|
||||
}
|
||||
@ -472,13 +486,14 @@ fn resolve_constr(e: @env, c: @ast::constr, sc: scopes, _v: vt<scopes>) {
|
||||
fn resolve_import(e: env, defid: ast::def_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: block(namespace) -> option::t<def>){
|
||||
name: ast::ident, lookup: block(namespace) -> option::t<def>,
|
||||
impls: [def_id]) {
|
||||
let val = lookup(ns_value), typ = lookup(ns_type),
|
||||
md = lookup(ns_module);
|
||||
if is_none(val) && is_none(typ) && is_none(md) {
|
||||
unresolved_err(e, cx, sp, name, "import");
|
||||
} else {
|
||||
e.imports.insert(id, resolved(val, typ, md, name, sp));
|
||||
e.imports.insert(id, resolved(val, typ, md, @impls, name, sp));
|
||||
}
|
||||
}
|
||||
// Temporarily disable this import and the imports coming after during
|
||||
@ -527,7 +542,7 @@ fn resolve_import(e: env, defid: ast::def_id, name: ast::ident,
|
||||
let end_id = ids[n_idents - 1u];
|
||||
if n_idents == 1u {
|
||||
register(e, defid.node, in_scope(sc), sp, name,
|
||||
{|ns| lookup_in_scope(e, sc, sp, end_id, ns) });
|
||||
{|ns| lookup_in_scope(e, sc, sp, end_id, ns) }, []);
|
||||
} else {
|
||||
alt lookup_in_scope(e, sc, sp, ids[0], ns_module) {
|
||||
none. {
|
||||
@ -537,9 +552,11 @@ fn resolve_import(e: env, defid: ast::def_id, name: ast::ident,
|
||||
let dcur = dcur_, i = 1u;
|
||||
while true {
|
||||
if i == n_idents - 1u {
|
||||
let impls = [];
|
||||
find_impls_in_mod(e, dcur, impls, some(end_id));
|
||||
register(e, defid.node, 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,
|
||||
@ -563,7 +580,7 @@ fn resolve_import(e: env, defid: ast::def_id, name: ast::ident,
|
||||
// import
|
||||
alt e.imports.find(defid.node) {
|
||||
some(resolving(sp)) {
|
||||
e.imports.insert(defid.node, resolved(none, none, none, "", sp));
|
||||
e.imports.insert(defid.node, resolved(none, none, none, @[], "", sp));
|
||||
}
|
||||
_ { }
|
||||
}
|
||||
@ -726,6 +743,11 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
|
||||
ast::item_obj(ob, ty_params, _) {
|
||||
ret lookup_in_obj(name, ob, ty_params, ns);
|
||||
}
|
||||
ast::item_impl(_, _, _) {
|
||||
if (name == "self" && ns == ns_value) {
|
||||
ret some(ast::def_self(local_def(it.id)));
|
||||
}
|
||||
}
|
||||
ast::item_tag(_, ty_params) {
|
||||
if ns == ns_type { ret lookup_in_ty_params(name, ty_params); }
|
||||
}
|
||||
@ -819,7 +841,6 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace)
|
||||
}
|
||||
}
|
||||
e.sess.bug("reached unreachable code in lookup_in_scope"); // sigh
|
||||
|
||||
}
|
||||
|
||||
fn lookup_in_ty_params(name: ident, ty_params: [ast::ty_param]) ->
|
||||
@ -999,7 +1020,7 @@ fn found_def_item(i: @ast::item, ns: namespace) -> option::t<def> {
|
||||
}
|
||||
_ { }
|
||||
}
|
||||
ret none::<def>;
|
||||
ret none;
|
||||
}
|
||||
|
||||
fn lookup_in_mod_strict(e: env, m: def, sp: span, name: ident,
|
||||
@ -1060,11 +1081,12 @@ fn lookup_import(e: env, defid: def_id, ns: namespace) -> option::t<def> {
|
||||
e.sess.span_err(sp, "cyclic import");
|
||||
ret none;
|
||||
}
|
||||
resolved(val, typ, md, _, _) {
|
||||
resolved(val, typ, md, _, _, _) {
|
||||
if e.used_imports.track {
|
||||
e.used_imports.data += [defid.node];
|
||||
}
|
||||
ret alt ns { ns_value. { val } ns_type. { typ } ns_module. { md } };
|
||||
ret alt ns { ns_value. { val } ns_type. { typ }
|
||||
ns_module. { md } };
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1136,22 +1158,20 @@ fn lookup_glob_in_mod(e: env, info: @indexed_mod, sp: span, id: ident,
|
||||
// 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, resolving(sp));
|
||||
info.glob_imported_names.insert(id, glob_resolving(sp));
|
||||
let val = lookup_in_globs(e, info.glob_imports, sp, id, ns_value, dr);
|
||||
let typ = lookup_in_globs(e, info.glob_imports, sp, id, ns_type, dr);
|
||||
let md = lookup_in_globs(e, info.glob_imports, sp, id, ns_module, dr);
|
||||
info.glob_imported_names.insert(id, resolved(val, typ, md, id, sp));
|
||||
info.glob_imported_names.insert(id, glob_resolved(val, typ, md));
|
||||
}
|
||||
alt info.glob_imported_names.get(id) {
|
||||
todo(_, _, _, _, _) { e.sess.bug("Shouldn't've put a todo in."); }
|
||||
//circularity is okay in import globs
|
||||
resolving(sp) { ret none::<def>; }
|
||||
resolved(val, typ, md, _, _) {
|
||||
glob_resolving(sp) { ret none::<def>; }
|
||||
glob_resolved(val, typ, md) {
|
||||
ret alt wanted_ns {
|
||||
ns_value. { val }
|
||||
ns_type. { typ }
|
||||
ns_module. { md }
|
||||
};
|
||||
ns_value. { val }
|
||||
ns_type. { typ }
|
||||
ns_module. { md }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1229,7 +1249,8 @@ fn index_mod(md: ast::_mod) -> mod_index {
|
||||
alt it.node {
|
||||
ast::item_const(_, _) | ast::item_fn(_, _) | ast::item_mod(_) |
|
||||
ast::item_native_mod(_) | ast::item_ty(_, _) |
|
||||
ast::item_res(_, _, _, _) | ast::item_obj(_, _, _) {
|
||||
ast::item_res(_, _, _, _) | ast::item_obj(_, _, _) |
|
||||
ast::item_impl(_, _, _) {
|
||||
add_to_index(index, it.ident, mie_item(it));
|
||||
}
|
||||
ast::item_tag(variants, _) {
|
||||
@ -1289,6 +1310,7 @@ fn ns_for_def(d: def) -> namespace {
|
||||
ast::def_use(_) { ns_module }
|
||||
ast::def_native_ty(_) { ns_type }
|
||||
ast::def_native_fn(_, _) { ns_value }
|
||||
ast::def_self(_) { ns_value }
|
||||
};
|
||||
}
|
||||
|
||||
@ -1558,7 +1580,7 @@ fn check_exports(e: @env) {
|
||||
alt x {
|
||||
mie_import_ident(id, _) {
|
||||
alt e.imports.get(id) {
|
||||
resolved(v, t, m, rid, _) {
|
||||
resolved(v, t, m, _, rid, _) {
|
||||
maybe_add_reexport(e, val.path + rid, v);
|
||||
maybe_add_reexport(e, val.path + rid, t);
|
||||
maybe_add_reexport(e, val.path + rid, m);
|
||||
@ -1596,6 +1618,115 @@ fn check_exports(e: @env) {
|
||||
};
|
||||
}
|
||||
|
||||
// Impl resolution
|
||||
|
||||
fn resolve_impls(e: @env, c: @ast::crate) {
|
||||
visit::visit_crate(*c, nil, visit::mk_vt(@{
|
||||
visit_block: bind visit_block_with_impl_scope(e, _, _, _),
|
||||
visit_item: bind visit_item_with_impl_scope(e, _, _, _),
|
||||
visit_expr: bind resolve_impl_in_expr(e, _, _, _)
|
||||
with *visit::default_visitor()
|
||||
}));
|
||||
}
|
||||
|
||||
fn find_impls_in_view_item(e: env, vi: @ast::view_item, &impls: [def_id]) {
|
||||
alt vi.node {
|
||||
ast::view_item_import(ident, _, id) {
|
||||
// FIXME if single name, simply look in our own iscope
|
||||
alt e.imports.get(id) {
|
||||
resolved(_, _, _, is, _, _) { impls += *is; }
|
||||
}
|
||||
}
|
||||
ast::view_item_import_from(base, names, _) {
|
||||
for nm in names {
|
||||
alt e.imports.get(nm.node.id) {
|
||||
resolved(_, _, _, is, _, _) { impls += *is; }
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::view_item_import_glob(ids, id) {
|
||||
alt 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); }
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
|
||||
fn find_impls_in_item(i: @ast::item, &impls: [def_id],
|
||||
name: option::t<ident>, _dir: dir) {
|
||||
// FIXME check exports
|
||||
alt i.node {
|
||||
ast::item_impl(_, _, _) {
|
||||
if alt name { some(n) { n == i.ident } _ { true } } {
|
||||
impls += [local_def(i.id)];
|
||||
}
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
|
||||
fn find_impls_in_mod(e: env, m: def, &impls: [def_id],
|
||||
name: option::t<ident>) {
|
||||
alt m {
|
||||
ast::def_mod(defid) {
|
||||
// FIXME external importing of impls
|
||||
if defid.crate == ast::local_crate {
|
||||
for i in option::get(e.mod_map.get(defid.node).m).items {
|
||||
find_impls_in_item(i, impls, name, outside);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
|
||||
type iscopes = list<@[def_id]>;
|
||||
|
||||
fn visit_block_with_impl_scope(e: @env, b: ast::blk, sc: iscopes,
|
||||
v: vt<iscopes>) {
|
||||
let impls = [];
|
||||
for vi in b.node.view_items { find_impls_in_view_item(*e, vi, impls); }
|
||||
for st in b.node.stmts {
|
||||
alt st.node {
|
||||
ast::stmt_decl(@{node: ast::decl_item(i), _}, _) {
|
||||
find_impls_in_item(i, impls, none, inside);
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
let sc = vec::len(impls) > 0u ? cons(@impls, @sc) : sc;
|
||||
visit::visit_block(b, sc, v);
|
||||
}
|
||||
|
||||
fn visit_item_with_impl_scope(e: @env, i: @ast::item, sc: iscopes,
|
||||
v: vt<iscopes>) {
|
||||
let sc = sc;
|
||||
alt i.node {
|
||||
ast::item_mod(m) {
|
||||
let impls = [];
|
||||
for vi in m.view_items { find_impls_in_view_item(*e, vi, impls); }
|
||||
for i in m.items { find_impls_in_item(i, impls, none, inside); }
|
||||
if vec::len(impls) > 0u { sc = cons(@impls, @sc); }
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
visit::visit_item(i, sc, v);
|
||||
}
|
||||
|
||||
fn resolve_impl_in_expr(e: @env, x: @ast::expr, sc: iscopes, v: vt<iscopes>) {
|
||||
alt x.node {
|
||||
ast::expr_field(_, _) { e.impl_map.insert(x.id, sc); }
|
||||
_ {}
|
||||
}
|
||||
visit::visit_expr(x, sc, v);
|
||||
}
|
||||
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
// fill-column: 78;
|
||||
|
@ -2678,6 +2678,9 @@ fn trans_local_var(cx: @block_ctxt, def: ast::def) -> local_var_result {
|
||||
assert (cx.fcx.llobjfields.contains_key(did.node));
|
||||
ret { val: cx.fcx.llobjfields.get(did.node), kind: owned };
|
||||
}
|
||||
ast::def_self(did) {
|
||||
ret lval_owned(cx, cx.fcx.llenv);
|
||||
}
|
||||
_ {
|
||||
bcx_ccx(cx).sess.span_unimpl
|
||||
(cx.sp, "unsupported def type in trans_local_def");
|
||||
@ -4946,6 +4949,7 @@ fn trans_item(cx: @local_ctxt, item: ast::item) {
|
||||
with *extend_path(cx, item.ident)};
|
||||
trans_obj(sub_cx, item.span, ob, ctor_id, tps);
|
||||
}
|
||||
ast::item_impl(_, _, _) { fail "FIXME[impl]"; }
|
||||
ast::item_res(dtor, dtor_id, tps, ctor_id) {
|
||||
trans_res_ctor(cx, item.span, dtor, ctor_id, tps);
|
||||
|
||||
|
@ -26,17 +26,14 @@ fn find_pre_post_native_mod(_m: native_mod) -> native_mod {
|
||||
fail;
|
||||
}
|
||||
|
||||
fn find_pre_post_obj(ccx: crate_ctxt, o: _obj) {
|
||||
fn do_a_method(ccx: crate_ctxt, m: @method) {
|
||||
assert (ccx.fm.contains_key(m.node.id));
|
||||
let fcx: fn_ctxt =
|
||||
{enclosing: ccx.fm.get(m.node.id),
|
||||
id: m.node.id,
|
||||
name: m.node.ident,
|
||||
ccx: ccx};
|
||||
find_pre_post_fn(fcx, m.node.meth);
|
||||
}
|
||||
for m: @method in o.methods { do_a_method(ccx, m); }
|
||||
fn find_pre_post_method(ccx: crate_ctxt, m: @method) {
|
||||
assert (ccx.fm.contains_key(m.node.id));
|
||||
let fcx: fn_ctxt =
|
||||
{enclosing: ccx.fm.get(m.node.id),
|
||||
id: m.node.id,
|
||||
name: m.node.ident,
|
||||
ccx: ccx};
|
||||
find_pre_post_fn(fcx, m.node.meth);
|
||||
}
|
||||
|
||||
fn find_pre_post_item(ccx: crate_ctxt, i: item) {
|
||||
@ -77,7 +74,8 @@ fn find_pre_post_item(ccx: crate_ctxt, i: item) {
|
||||
ccx: ccx};
|
||||
find_pre_post_fn(fcx, dtor);
|
||||
}
|
||||
item_obj(o, _, _) { find_pre_post_obj(ccx, o); }
|
||||
item_obj(o, _, _) {for m in o.methods { find_pre_post_method(ccx, m); }}
|
||||
item_impl(_, _, ms) { for m in ms { find_pre_post_method(ccx, m); } }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2702,20 +2702,12 @@ fn substitute_type_params(cx: ctxt, substs: [ty::t], typ: t) -> t {
|
||||
|
||||
fn def_has_ty_params(def: ast::def) -> bool {
|
||||
alt def {
|
||||
ast::def_fn(_, _) { ret true; }
|
||||
ast::def_obj_field(_, _) { ret false; }
|
||||
ast::def_mod(_) { ret false; }
|
||||
ast::def_const(_) { ret false; }
|
||||
ast::def_arg(_, _) { ret false; }
|
||||
ast::def_local(_, _) { ret false; }
|
||||
ast::def_upvar(_, _, _) { ret false; }
|
||||
ast::def_variant(_, _) { ret true; }
|
||||
ast::def_ty(_) { ret false; }
|
||||
ast::def_ty_param(_, _) { ret false; }
|
||||
ast::def_binding(_) { ret false; }
|
||||
ast::def_use(_) { ret false; }
|
||||
ast::def_native_ty(_) { ret false; }
|
||||
ast::def_native_fn(_, _) { ret true; }
|
||||
ast::def_obj_field(_, _) | ast::def_mod(_) | ast::def_const(_) |
|
||||
ast::def_arg(_, _) | ast::def_local(_, _) | ast::def_upvar(_, _, _) |
|
||||
ast::def_ty_param(_, _) | ast::def_binding(_) | ast::def_use(_) |
|
||||
ast::def_native_ty(_) | ast::def_self(_) | ast::def_ty(_) { false }
|
||||
ast::def_fn(_, _) | ast::def_variant(_, _) |
|
||||
ast::def_native_fn(_, _) { true }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,9 @@ tag obj_info {
|
||||
anon_obj([ast::obj_field], option::t<ty::sty>);
|
||||
}
|
||||
|
||||
type crate_ctxt = {mutable obj_infos: [obj_info], tcx: ty::ctxt};
|
||||
type crate_ctxt = {mutable obj_infos: [obj_info],
|
||||
impl_map: resolve::impl_map,
|
||||
tcx: ty::ctxt};
|
||||
|
||||
type fn_ctxt =
|
||||
// var_bindings, locals and next_var_id are shared
|
||||
@ -89,6 +91,7 @@ fn ty_param_kinds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
|
||||
let typ = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, sp, id.node));
|
||||
ret {kinds: no_kinds, ty: typ};
|
||||
}
|
||||
ast::def_self(id) { fail "FIXME[impl]"; }
|
||||
ast::def_fn(id, _) { ret ty::lookup_item_type(fcx.ccx.tcx, id); }
|
||||
ast::def_native_fn(id, _) { ret ty::lookup_item_type(fcx.ccx.tcx, id); }
|
||||
ast::def_const(id) { ret ty::lookup_item_type(fcx.ccx.tcx, id); }
|
||||
@ -686,7 +689,7 @@ mod collect {
|
||||
}
|
||||
fn convert(cx: @ctxt, it: @ast::item) {
|
||||
alt it.node {
|
||||
ast::item_mod(_) {
|
||||
ast::item_mod(_) | ast::item_impl(_, _, _) {
|
||||
// ignore item_mod, it has no type.
|
||||
}
|
||||
ast::item_native_mod(native_mod) {
|
||||
@ -2657,12 +2660,15 @@ fn check_for_main_fn(tcx: ty::ctxt, crate: @ast::crate) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_crate(tcx: ty::ctxt, crate: @ast::crate) {
|
||||
fn check_crate(tcx: ty::ctxt, impl_map: resolve::impl_map,
|
||||
crate: @ast::crate) {
|
||||
collect::collect_item_types(tcx, crate);
|
||||
|
||||
let obj_infos: [obj_info] = [];
|
||||
|
||||
let ccx = @{mutable obj_infos: obj_infos, tcx: tcx};
|
||||
let ccx = @{mutable obj_infos: obj_infos,
|
||||
impl_map: impl_map,
|
||||
tcx: tcx};
|
||||
let visit =
|
||||
visit::mk_simple_visitor(@{visit_item: bind check_item(ccx, _)
|
||||
with *visit::default_simple_visitor()});
|
||||
|
@ -33,9 +33,8 @@ tag def {
|
||||
def_const(def_id);
|
||||
def_arg(def_id, mode);
|
||||
def_local(def_id, let_style);
|
||||
def_variant(def_id, /* tag */def_id);
|
||||
|
||||
/* variant */
|
||||
def_variant(def_id /* tag */, def_id /* variant */);
|
||||
def_self(def_id);
|
||||
def_ty(def_id);
|
||||
def_ty_param(uint, kind);
|
||||
def_binding(def_id);
|
||||
@ -507,6 +506,7 @@ tag item_ {
|
||||
node_id /* dtor id */,
|
||||
[ty_param],
|
||||
node_id /* ctor id */);
|
||||
item_impl(@path /* iface */, @ty /* self */, [@method]);
|
||||
}
|
||||
|
||||
type native_item =
|
||||
|
@ -36,6 +36,7 @@ fn def_id_of_def(d: def) -> def_id {
|
||||
alt d {
|
||||
def_fn(id, _) { ret id; }
|
||||
def_obj_field(id, _) { ret id; }
|
||||
def_self(id) { ret id; }
|
||||
def_mod(id) { ret id; }
|
||||
def_native_mod(id) { ret id; }
|
||||
def_const(id) { ret id; }
|
||||
|
@ -235,6 +235,10 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
|
||||
methods: vec::map(fld.fold_method, o.methods)},
|
||||
typms, d)
|
||||
}
|
||||
item_impl(iface, ty, methods) {
|
||||
item_impl(fld.fold_path(iface), fld.fold_ty(ty),
|
||||
vec::map(fld.fold_method, methods))
|
||||
}
|
||||
item_res(dtor, did, typms, cid) {
|
||||
item_res(fld.fold_fn(dtor), did, typms, cid)
|
||||
}
|
||||
|
@ -155,7 +155,8 @@ fn bad_expr_word_table() -> hashmap<str, ()> {
|
||||
"cont", "ret", "be", "fail", "type", "resource", "check",
|
||||
"assert", "claim", "native", "fn", "lambda", "pure",
|
||||
"unsafe", "block", "import", "export", "let", "const",
|
||||
"log", "log_err", "tag", "obj", "self", "copy", "sendfn"] {
|
||||
"log", "log_err", "tag", "obj", "self", "copy", "sendfn",
|
||||
"impl"] {
|
||||
words.insert(word, ());
|
||||
}
|
||||
words
|
||||
@ -941,8 +942,8 @@ fn parse_bottom_expr(p: parser) -> @ast::expr {
|
||||
let e = parse_expr(p);
|
||||
ex = ast::expr_copy(e);
|
||||
hi = e.span.hi;
|
||||
} else if eat_word(p, "self") {
|
||||
expect(p, token::DOT);
|
||||
} else if is_word(p, "self") && p.look_ahead(1u) == token::DOT {
|
||||
p.bump(); p.bump();
|
||||
// The rest is a call expression.
|
||||
let f: @ast::expr = parse_self_method(p);
|
||||
let es =
|
||||
@ -1873,6 +1874,17 @@ fn parse_item_obj(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
||||
attrs);
|
||||
}
|
||||
|
||||
fn parse_item_impl(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
||||
let lo = p.get_last_lo_pos(), ty = parse_ty(p, false);
|
||||
expect(p, token::COLON);
|
||||
let path = parse_path(p), meths = [];
|
||||
expect(p, token::LBRACE);
|
||||
while !eat(p, token::RBRACE) { meths += [parse_method(p)]; }
|
||||
ret mk_item(p, lo, p.get_last_hi_pos(),
|
||||
path.node.idents[vec::len(path.node.idents) - 1u],
|
||||
ast::item_impl(path, ty, meths), attrs);
|
||||
}
|
||||
|
||||
fn parse_item_res(p: parser, attrs: [ast::attribute]) -> @ast::item {
|
||||
let lo = p.get_last_lo_pos();
|
||||
let ident = parse_value_ident(p);
|
||||
@ -2139,14 +2151,15 @@ fn parse_item(p: parser, attrs: [ast::attribute]) -> option::t<@ast::item> {
|
||||
ret some(parse_item_mod(p, attrs));
|
||||
} else if eat_word(p, "native") {
|
||||
ret some(parse_item_native_mod(p, attrs));
|
||||
}
|
||||
if eat_word(p, "type") {
|
||||
} if eat_word(p, "type") {
|
||||
ret some(parse_item_type(p, attrs));
|
||||
} else if eat_word(p, "tag") {
|
||||
ret some(parse_item_tag(p, attrs));
|
||||
} else if is_word(p, "obj") && p.look_ahead(1u) != token::LPAREN {
|
||||
p.bump();
|
||||
ret some(parse_item_obj(p, attrs));
|
||||
} else if eat_word(p, "impl") {
|
||||
ret some(parse_item_impl(p, attrs));
|
||||
} else if eat_word(p, "resource") {
|
||||
ret some(parse_item_res(p, attrs));
|
||||
} else { ret none; }
|
||||
|
@ -483,6 +483,22 @@ fn print_item(s: ps, &&item: @ast::item) {
|
||||
}
|
||||
bclose(s, item.span);
|
||||
}
|
||||
ast::item_impl(path, ty, methods) {
|
||||
head(s, "impl");
|
||||
print_type(s, ty);
|
||||
word_space(s, ":");
|
||||
print_path(s, path, false);
|
||||
bopen(s);
|
||||
for meth in methods {
|
||||
hardbreak_if_not_bol(s);
|
||||
maybe_print_comment(s, meth.span.lo);
|
||||
print_fn(s, meth.node.meth.decl, meth.node.meth.proto,
|
||||
meth.node.ident, [], []);
|
||||
word(s.s, " ");
|
||||
print_block(s, meth.node.meth.body);
|
||||
}
|
||||
bclose(s, item.span);
|
||||
}
|
||||
ast::item_res(dt, dt_id, tps, ct_id) {
|
||||
head(s, "resource");
|
||||
word(s.s, item.ident);
|
||||
|
@ -105,6 +105,14 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
|
||||
e, v);
|
||||
}
|
||||
}
|
||||
item_impl(path, ty, methods) {
|
||||
visit_path(path, e, v);
|
||||
visit_ty(ty, e, v);
|
||||
for m in methods {
|
||||
v.visit_fn(m.node.meth, [], m.span, some(m.node.ident), m.node.id,
|
||||
e, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,7 +141,8 @@ fn visit_ty<E>(t: @ty, e: E, v: vt<E>) {
|
||||
v.visit_ty(m.node.output, e, v);
|
||||
}
|
||||
}
|
||||
ty_path(p, _) { for tp: @ty in p.node.types { v.visit_ty(tp, e, v); } }
|
||||
ty_path(p, _) { visit_path(p, e, v); }
|
||||
ty_type. {/* no-op */ }
|
||||
ty_constr(t, cs) {
|
||||
v.visit_ty(t, e, v);
|
||||
for tc: @spanned<constr_general_<@path, node_id>> in cs {
|
||||
@ -149,10 +158,14 @@ fn visit_constr<E>(_operator: @path, _sp: span, _id: node_id, _e: E,
|
||||
// default
|
||||
}
|
||||
|
||||
fn visit_path<E>(p: @path, e: E, v: vt<E>) {
|
||||
for tp: @ty in p.node.types { v.visit_ty(tp, e, v); }
|
||||
}
|
||||
|
||||
fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
|
||||
alt p.node {
|
||||
pat_tag(path, children) {
|
||||
for tp: @ty in path.node.types { v.visit_ty(tp, e, v); }
|
||||
visit_path(path, e, v);
|
||||
for child: @pat in children { v.visit_pat(child, e, v); }
|
||||
}
|
||||
pat_rec(fields, _) {
|
||||
@ -286,7 +299,7 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
|
||||
}
|
||||
expr_field(x, _) { v.visit_expr(x, e, v); }
|
||||
expr_index(a, b) { v.visit_expr(a, e, v); v.visit_expr(b, e, v); }
|
||||
expr_path(p) { for tp: @ty in p.node.types { v.visit_ty(tp, e, v); } }
|
||||
expr_path(p) { visit_path(p, e, v); }
|
||||
expr_fail(eo) { visit_expr_opt(eo, e, v); }
|
||||
expr_break. { }
|
||||
expr_cont. { }
|
||||
|
Loading…
x
Reference in New Issue
Block a user