First cut at dtors for classes
Classes with dtors should compile now. Haven't yet tested whether they actually run correctly. Beginnings of support for #2295, though that won't be done until there's more test cases and resources are removed.
This commit is contained in:
@@ -214,6 +214,13 @@ fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) {
|
||||
vfn(self_id);
|
||||
vfn(parent_id.node);
|
||||
}
|
||||
// not sure if this should be here? FIXME
|
||||
visit::fk_dtor(tps, self_id, parent_id) {
|
||||
vec::iter(tps) {|tp| vfn(tp.id)}
|
||||
vfn(id);
|
||||
vfn(self_id);
|
||||
vfn(parent_id.node);
|
||||
}
|
||||
visit::fk_item_fn(_, tps) |
|
||||
visit::fk_res(_, tps, _) {
|
||||
vec::iter(tps) {|tp| vfn(tp.id)}
|
||||
|
||||
@@ -187,7 +187,8 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
|
||||
encode_def_id(ebml_w, local_def(it.id));
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
item_class(_, _, items, ctor, _) {
|
||||
// FIXME: I don't *think* dtor needs to be serialized?
|
||||
item_class(_, _, items, ctor, _dtor, _) {
|
||||
add_to_index(ebml_w, path, index, it.ident);
|
||||
ebml_w.start_tag(tag_paths_data_item);
|
||||
encode_name(ebml_w, it.ident);
|
||||
@@ -621,7 +622,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
||||
encode_enum_variant_info(ecx, ebml_w, item.id, variants,
|
||||
path, index, tps);
|
||||
}
|
||||
item_class(tps, ifaces, items, ctor, rp) {
|
||||
// FIXME: not sure if the dtor should be serialized
|
||||
item_class(tps, ifaces, items, ctor, _dtor, rp) {
|
||||
/* First, encode the fields and methods
|
||||
These come first because we need to write them to make
|
||||
the index, and the index needs to be in the item for the
|
||||
@@ -801,7 +803,8 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
||||
encode_info_for_item(ecx, ebml_w, i, index, *pt);
|
||||
/* encode ctor, then encode items */
|
||||
alt i.node {
|
||||
item_class(tps, _, _, ctor, _) {
|
||||
// FIXME: not doing anything with dtor
|
||||
item_class(tps, _, _, ctor, _, _) {
|
||||
/* this is assuming that ctors aren't inlined...
|
||||
probably shouldn't assume that */
|
||||
#debug("encoding info for ctor %s %d", i.ident,
|
||||
|
||||
@@ -47,6 +47,8 @@ enum ast_node {
|
||||
node_local(uint),
|
||||
// Constructor for either a resource or a class
|
||||
node_ctor(ident, [ty_param], a_ctor, @path),
|
||||
// Destructor for a class
|
||||
node_dtor([ty_param], @class_dtor, def_id, @path),
|
||||
node_block(blk),
|
||||
}
|
||||
|
||||
@@ -134,6 +136,12 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
|
||||
cx.map.insert(id, node_ctor(nm, tps, class_ctor(ct, parent_id),
|
||||
@cx.path));
|
||||
}
|
||||
visit::fk_dtor(tps, self_id, parent_id) {
|
||||
let dt = @{node: {id: id, self_id: self_id, body: body},
|
||||
span: sp};
|
||||
cx.map.insert(id, node_dtor(tps, dt, parent_id, @cx.path));
|
||||
}
|
||||
|
||||
_ {}
|
||||
}
|
||||
visit::visit_fn(fk, decl, body, sp, id, cx, v);
|
||||
@@ -204,7 +212,7 @@ fn map_item(i: @item, cx: ctx, v: vt) {
|
||||
cx.map.insert(nitem.id, node_native_item(nitem, abi, @cx.path));
|
||||
}
|
||||
}
|
||||
item_class(tps, ifces, items, ctor, _) {
|
||||
item_class(tps, ifces, items, ctor, dtor, _) {
|
||||
let (_, ms) = ast_util::split_class_items(items);
|
||||
// Map iface refs to their parent classes. This is
|
||||
// so we can find the self_ty
|
||||
@@ -283,9 +291,12 @@ fn node_id_to_str(map: map, id: node_id) -> str {
|
||||
some(node_local(_)) { // FIXME: add more info here
|
||||
#fmt["local (id=%?)", id]
|
||||
}
|
||||
some(node_ctor(_, _, _, _)) { // FIXME: add more info here
|
||||
some(node_ctor(*)) { // FIXME: add more info here
|
||||
#fmt["node_ctor (id=%?)", id]
|
||||
}
|
||||
some(node_dtor(*)) { // FIXME: add more info here
|
||||
#fmt["node_dtor (id=%?)", id]
|
||||
}
|
||||
some(node_block(_)) {
|
||||
#fmt["block"]
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
|
||||
let cap_clause = alt fk {
|
||||
visit::fk_anon(_, cc) | visit::fk_fn_block(cc) { cc }
|
||||
visit::fk_item_fn(*) | visit::fk_method(*) |
|
||||
visit::fk_res(*) | visit::fk_ctor(*) { @[] }
|
||||
visit::fk_res(*) | visit::fk_ctor(*) | visit::fk_dtor(*) { @[] }
|
||||
};
|
||||
let captured_vars = (*cap_clause).map { |cap_item|
|
||||
let cap_def = cx.tcx.def_map.get(cap_item.id);
|
||||
|
||||
@@ -375,7 +375,7 @@ fn resolve_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
|
||||
|
||||
let fn_cx = alt fk {
|
||||
visit::fk_item_fn(*) | visit::fk_method(*) | visit::fk_res(*) |
|
||||
visit::fk_ctor(*) {
|
||||
visit::fk_ctor(*) | visit::fk_dtor(*) {
|
||||
// Top-level functions are a root scope.
|
||||
{parent: some(id), closure_parent: some(id) with cx}
|
||||
}
|
||||
|
||||
@@ -437,7 +437,7 @@ fn resolve_names(e: @env, c: @ast::crate) {
|
||||
ast::item_impl(_, _, ifce, _, _) {
|
||||
ifce.iter {|p| resolve_iface_ref(p, sc, e);}
|
||||
}
|
||||
ast::item_class(_, ifaces, _, _, _) {
|
||||
ast::item_class(_, ifaces, _, _, _, _) {
|
||||
for ifaces.each {|p|
|
||||
resolve_iface_ref(p, sc, e);
|
||||
}
|
||||
@@ -564,22 +564,31 @@ fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt<scopes>) {
|
||||
v.visit_ty(m.decl.output, msc, v);
|
||||
}
|
||||
}
|
||||
ast::item_class(tps, ifaces, members, ctor, _) {
|
||||
ast::item_class(tps, ifaces, members, ctor, m_dtor, _) {
|
||||
visit::visit_ty_params(tps, sc, v);
|
||||
// Can maybe skip this now that we require self on class fields
|
||||
let class_scope = cons(scope_item(i), @sc);
|
||||
/* visit the constructor... */
|
||||
let ctor_scope = cons(scope_method(ctor.node.self_id, tps),
|
||||
@class_scope);
|
||||
/*
|
||||
but, I should visit the ifaces refs in the class scope, no?
|
||||
*/
|
||||
/* visit the iface refs in the class scope */
|
||||
for ifaces.each {|p|
|
||||
visit::visit_path(p.path, class_scope, v);
|
||||
}
|
||||
// FIXME: should be fk_ctor?
|
||||
visit_fn_with_scope(e, visit::fk_item_fn(i.ident, tps), ctor.node.dec,
|
||||
ctor.node.body, ctor.span, ctor.node.id,
|
||||
ctor_scope, v);
|
||||
option::iter(m_dtor) {|dtor|
|
||||
let dtor_scope = cons(scope_method(dtor.node.self_id, tps),
|
||||
@class_scope);
|
||||
|
||||
visit_fn_with_scope(e, visit::fk_dtor(tps, dtor.node.self_id,
|
||||
local_def(i.id)),
|
||||
ast_util::dtor_dec(),
|
||||
dtor.node.body, dtor.span, dtor.node.id,
|
||||
dtor_scope, v);
|
||||
};
|
||||
/* visit the items */
|
||||
for members.each {|cm|
|
||||
alt cm.node {
|
||||
@@ -625,7 +634,8 @@ fn visit_fn_with_scope(e: @env, fk: visit::fn_kind, decl: ast::fn_decl,
|
||||
for decl.constraints.each {|c| resolve_constr(e, c, sc, v); }
|
||||
let scope = alt fk {
|
||||
visit::fk_item_fn(_, tps) | visit::fk_res(_, tps, _) |
|
||||
visit::fk_method(_, tps, _) | visit::fk_ctor(_, tps, _, _) {
|
||||
visit::fk_method(_, tps, _) | visit::fk_ctor(_, tps, _, _) |
|
||||
visit::fk_dtor(tps, _, _) {
|
||||
scope_bare_fn(decl, id, tps) }
|
||||
visit::fk_anon(ast::proto_bare, _) {
|
||||
scope_bare_fn(decl, id, []) }
|
||||
@@ -1041,7 +1051,7 @@ fn lookup_in_scope(e: env, sc: scopes, sp: span, name: ident, ns: namespace,
|
||||
ast::item_native_mod(m) {
|
||||
ret lookup_in_local_native_mod(e, it.id, sp, name, ns);
|
||||
}
|
||||
ast::item_class(tps, _, members, ctor, _) {
|
||||
ast::item_class(tps, _, members, ctor, _, _) {
|
||||
if ns == ns_type {
|
||||
ret lookup_in_ty_params(e, name, tps);
|
||||
}
|
||||
@@ -1633,7 +1643,7 @@ fn index_mod(md: ast::_mod) -> mod_index {
|
||||
variant_idx += 1u;
|
||||
}
|
||||
}
|
||||
ast::item_class(tps, _, items, ctor, _) {
|
||||
ast::item_class(tps, _, items, ctor, _, _) {
|
||||
// add the class name itself
|
||||
add_to_index(index, it.ident, mie_item(it));
|
||||
// add the constructor decl
|
||||
@@ -2236,7 +2246,7 @@ fn find_impls_in_item(e: env, i: @ast::item, &impls: [@_impl],
|
||||
})}];
|
||||
}
|
||||
}
|
||||
ast::item_class(tps, ifces, items, _, _) {
|
||||
ast::item_class(tps, ifces, items, _, _, _) {
|
||||
let (_, mthds) = ast_util::split_class_items(items);
|
||||
let n_tps = tps.len();
|
||||
vec::iter(ifces) {|p|
|
||||
|
||||
@@ -4443,6 +4443,15 @@ fn trans_class_ctor(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
|
||||
finish_fn(fcx, lltop);
|
||||
}
|
||||
|
||||
fn trans_class_dtor(ccx: @crate_ctxt, path: path,
|
||||
body: ast::blk, lldtor_decl: ValueRef,
|
||||
dtor_id: ast::node_id,
|
||||
parent_id: ast::def_id) {
|
||||
let class_ty = ty::lookup_item_type(ccx.tcx, parent_id).ty;
|
||||
trans_fn(ccx, path, ast_util::dtor_dec(),
|
||||
body, lldtor_decl, impl_self(class_ty), none, dtor_id);
|
||||
}
|
||||
|
||||
fn trans_item(ccx: @crate_ctxt, item: ast::item) {
|
||||
let _icx = ccx.insn_ctxt("trans_item");
|
||||
let path = alt check ccx.tcx.items.get(item.id) {
|
||||
@@ -4509,7 +4518,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
|
||||
};
|
||||
native::trans_native_mod(ccx, native_mod, abi);
|
||||
}
|
||||
ast::item_class(tps, _ifaces, items, ctor, _) {
|
||||
ast::item_class(tps, _ifaces, items, ctor, m_dtor, _) {
|
||||
if tps.len() == 0u {
|
||||
let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps),
|
||||
// FIXME: vtables have to get filled in depending
|
||||
@@ -4519,6 +4528,11 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
|
||||
trans_class_ctor(ccx, *path, ctor.node.dec, ctor.node.body,
|
||||
get_item_val(ccx, ctor.node.id), psubsts,
|
||||
ctor.node.id, local_def(item.id), ctor.span);
|
||||
option::iter(m_dtor) {|dtor|
|
||||
trans_class_dtor(ccx, *path, dtor.node.body,
|
||||
get_item_val(ccx, dtor.node.id),
|
||||
dtor.node.id, local_def(item.id));
|
||||
};
|
||||
}
|
||||
// If there are ty params, the ctor will get monomorphized
|
||||
|
||||
@@ -4744,6 +4758,12 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_map::node_dtor(tps, dt, parent_id, pt) {
|
||||
let my_path = *pt + [path_name("dtor")];
|
||||
let t = ty::node_id_to_type(ccx.tcx, dt.node.id);
|
||||
register_fn_full(ccx, dt.span, my_path, dt.node.id, t)
|
||||
}
|
||||
|
||||
ast_map::node_variant(v, enm, pth) {
|
||||
assert v.node.args.len() != 0u;
|
||||
let pth = *pth + [path_name(enm.ident), path_name(v.node.name)];
|
||||
|
||||
@@ -94,7 +94,7 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id,
|
||||
method_from_methods(ms, name)
|
||||
}
|
||||
ast_map::node_item(@{node:
|
||||
ast::item_class(_, _, items, _, _), _}, _) {
|
||||
ast::item_class(_, _, items, _, _, _), _}, _) {
|
||||
let (_,ms) = split_class_items(items);
|
||||
method_from_methods(ms, name)
|
||||
}
|
||||
|
||||
@@ -102,8 +102,11 @@ fn traverse_public_item(cx: ctx, item: @item) {
|
||||
}
|
||||
}
|
||||
}
|
||||
item_class(tps, _ifaces, items, ctor, _) {
|
||||
item_class(tps, _ifaces, items, ctor, m_dtor, _) {
|
||||
cx.rmap.insert(ctor.node.id, ());
|
||||
option::iter(m_dtor) {|dtor|
|
||||
cx.rmap.insert(dtor.node.id, ());
|
||||
}
|
||||
for vec::each(items) {|item|
|
||||
alt item.node {
|
||||
class_method(m) {
|
||||
|
||||
@@ -57,7 +57,7 @@ fn find_pre_post_item(ccx: crate_ctxt, i: item) {
|
||||
ccx: ccx};
|
||||
find_pre_post_fn(fcx, body);
|
||||
}
|
||||
item_class(_,_,_,_,_) {
|
||||
item_class(*) {
|
||||
fail "find_pre_post_item: shouldn't be called on item_class";
|
||||
}
|
||||
item_impl(_, _, _, _, ms) {
|
||||
|
||||
@@ -2326,7 +2326,7 @@ fn impl_iface(cx: ctxt, id: ast::def_id) -> option<t> {
|
||||
_, _, some(@{id: id, _}), _, _), _}, _)) {
|
||||
some(node_id_to_type(cx, id))
|
||||
}
|
||||
some(ast_map::node_item(@{node: ast::item_class(_, _, _, _, _),
|
||||
some(ast_map::node_item(@{node: ast::item_class(_, _, _, _, _, _),
|
||||
_},_)) {
|
||||
alt cx.def_map.find(id.node) {
|
||||
some(def_ty(iface_id)) {
|
||||
@@ -2408,6 +2408,10 @@ fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
|
||||
ast_map::node_ctor(nm, _, _, path) {
|
||||
*path + [ast_map::path_name(nm)]
|
||||
}
|
||||
ast_map::node_dtor(_, _, _, path) {
|
||||
*path + [ast_map::path_name("dtor")]
|
||||
}
|
||||
|
||||
|
||||
ast_map::node_expr(_) | ast_map::node_arg(_, _) |
|
||||
ast_map::node_local(_) | ast_map::node_export(_, _) |
|
||||
@@ -2527,7 +2531,7 @@ fn lookup_class_fields(cx: ctxt, did: ast::def_id) -> [field_ty] {
|
||||
alt cx.items.find(did.node) {
|
||||
some(ast_map::node_item(i,_)) {
|
||||
alt i.node {
|
||||
ast::item_class(_, _, items, _, _) {
|
||||
ast::item_class(_, _, items, _, _, _) {
|
||||
class_field_tys(items)
|
||||
}
|
||||
_ { cx.sess.bug("class ID bound to non-class"); }
|
||||
@@ -2569,7 +2573,7 @@ pure fn is_public(f: field_ty) -> bool {
|
||||
fn lookup_class_method_ids(cx: ctxt, did: ast::def_id)
|
||||
: is_local(did) -> [{name: ident, id: node_id, vis: visibility}] {
|
||||
alt cx.items.find(did.node) {
|
||||
some(ast_map::node_item(@{node: item_class(_,_,items,_,_), _}, _)) {
|
||||
some(ast_map::node_item(@{node: item_class(_,_,items,_,_,_), _}, _)) {
|
||||
let (_,ms) = split_class_items(items);
|
||||
vec::map(ms, {|m| {name: m.ident, id: m.id,
|
||||
vis: m.vis}})
|
||||
|
||||
@@ -926,7 +926,7 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
|
||||
tcx.tcache.insert(local_def(it.id), tpt);
|
||||
ret tpt;
|
||||
}
|
||||
ast::item_class(tps, _, _, _, rp) {
|
||||
ast::item_class(tps, _, _, _, _, rp) {
|
||||
let {bounds,substs} = mk_substs(ccx, tps, rp);
|
||||
let t = ty::mk_class(tcx, local_def(it.id), substs);
|
||||
let tpt = {bounds: bounds, rp: rp, ty: t};
|
||||
@@ -1487,7 +1487,7 @@ mod collect {
|
||||
ty_of_ty_method(ccx, m, rp)
|
||||
};
|
||||
}
|
||||
ast_map::node_item(@{node: ast::item_class(_,_,its,_,rp), _}, _) {
|
||||
ast_map::node_item(@{node: ast::item_class(_,_,its,_,_,rp), _}, _) {
|
||||
let (_,ms) = split_class_items(its);
|
||||
// All methods need to be stored, since lookup_method
|
||||
// relies on the same method cache for self-calls
|
||||
@@ -1654,7 +1654,7 @@ mod collect {
|
||||
write_ty_to_tcx(tcx, it.id, tpt.ty);
|
||||
ensure_iface_methods(ccx, it.id);
|
||||
}
|
||||
ast::item_class(tps, ifaces, members, ctor, rp) {
|
||||
ast::item_class(tps, ifaces, members, ctor, m_dtor, rp) {
|
||||
// Write the class type
|
||||
let tpt = ty_of_item(ccx, it);
|
||||
write_ty_to_tcx(tcx, it.id, tpt.ty);
|
||||
@@ -1671,6 +1671,22 @@ mod collect {
|
||||
{bounds: tpt.bounds,
|
||||
rp: ast::rp_none,
|
||||
ty: t_ctor});
|
||||
option::iter(m_dtor) {|dtor|
|
||||
// Write the dtor type
|
||||
let t_dtor = ty::mk_fn(tcx,
|
||||
// not sure about empty_rscope
|
||||
// FIXME
|
||||
ty_of_fn_decl(ccx,
|
||||
empty_rscope,
|
||||
ast::proto_any,
|
||||
ast_util::dtor_dec(),
|
||||
none));
|
||||
write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
|
||||
tcx.tcache.insert(local_def(dtor.node.id),
|
||||
{bounds: tpt.bounds,
|
||||
rp: ast::rp_none,
|
||||
ty: t_dtor});
|
||||
};
|
||||
ensure_iface_methods(ccx, it.id);
|
||||
/* FIXME: check for proper public/privateness */
|
||||
// Write the type of each of the members
|
||||
@@ -2441,7 +2457,7 @@ fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id) -> ty_param_substs_and_ty {
|
||||
raw_ty: fcx.ccx.to_ty(type_rscope(rp), st)}
|
||||
}
|
||||
some(ast_map::node_item(@{node: ast::item_class(ts,
|
||||
_,_,_,rp), id: class_id, _},_)) {
|
||||
_,_,_,_,rp), id: class_id, _},_)) {
|
||||
/* If the impl is a class, the self ty is just the class ty
|
||||
(doing a no-op subst for the ty params; in the next step,
|
||||
we substitute in fresh vars for them)
|
||||
@@ -4443,7 +4459,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
|
||||
let self_ty = ccx.to_ty(type_rscope(rp), ty);
|
||||
for ms.each {|m| check_method(ccx, m, self_ty);}
|
||||
}
|
||||
ast::item_class(tps, ifaces, members, ctor, rp) {
|
||||
ast::item_class(tps, ifaces, members, ctor, m_dtor, rp) {
|
||||
let cid = some(it.id), tcx = ccx.tcx;
|
||||
let class_t = ty::node_id_to_type(tcx, it.id);
|
||||
let members_info = class_types(ccx, members, rp);
|
||||
@@ -4458,6 +4474,14 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
|
||||
// Write the ctor's self's type
|
||||
write_ty_to_tcx(tcx, ctor.node.self_id, class_t);
|
||||
|
||||
option::iter(m_dtor) {|dtor|
|
||||
// typecheck the dtor
|
||||
check_bare_fn(class_ccx, ast_util::dtor_dec(),
|
||||
dtor.node.body, dtor.node.id,
|
||||
some(class_t));
|
||||
// Write the dtor's self's type
|
||||
write_ty_to_tcx(tcx, dtor.node.self_id, class_t);
|
||||
};
|
||||
// typecheck the members
|
||||
for members.each {|m| check_class_member(class_ccx, class_t, m); }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user