diff options
| author | Tim Chevalier <chevalier@alum.wellesley.edu> | 2012-05-14 14:13:32 -0700 |
|---|---|---|
| committer | Tim Chevalier <chevalier@alum.wellesley.edu> | 2012-05-14 14:26:10 -0700 |
| commit | 5428a22b95ccd8c84a402e2f5cb4aa53ddc6f4d4 (patch) | |
| tree | 5d5b8f41d0011249fd613c23d6033d05f36101c3 /src | |
| parent | 89cd2f6bd01e66f41b8dc49dd09930aa86cd2bd9 (diff) | |
| download | rust-5428a22b95ccd8c84a402e2f5cb4aa53ddc6f4d4.tar.gz rust-5428a22b95ccd8c84a402e2f5cb4aa53ddc6f4d4.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustsyntax/ast.rs | 12 | ||||
| -rw-r--r-- | src/librustsyntax/ast_util.rs | 6 | ||||
| -rw-r--r-- | src/librustsyntax/fold.rs | 11 | ||||
| -rw-r--r-- | src/librustsyntax/parse/parser.rs | 61 | ||||
| -rw-r--r-- | src/librustsyntax/parse/token.rs | 2 | ||||
| -rw-r--r-- | src/librustsyntax/print/pprust.rs | 7 | ||||
| -rw-r--r-- | src/librustsyntax/visit.rs | 23 | ||||
| -rw-r--r-- | src/rustc/metadata/astencode.rs | 7 | ||||
| -rw-r--r-- | src/rustc/metadata/encoder.rs | 9 | ||||
| -rw-r--r-- | src/rustc/middle/ast_map.rs | 15 | ||||
| -rw-r--r-- | src/rustc/middle/kind.rs | 2 | ||||
| -rw-r--r-- | src/rustc/middle/region.rs | 2 | ||||
| -rw-r--r-- | src/rustc/middle/resolve.rs | 28 | ||||
| -rw-r--r-- | src/rustc/middle/trans/base.rs | 22 | ||||
| -rw-r--r-- | src/rustc/middle/trans/impl.rs | 2 | ||||
| -rw-r--r-- | src/rustc/middle/trans/reachable.rs | 5 | ||||
| -rw-r--r-- | src/rustc/middle/tstate/pre_post_conditions.rs | 2 | ||||
| -rw-r--r-- | src/rustc/middle/ty.rs | 10 | ||||
| -rw-r--r-- | src/rustc/middle/typeck.rs | 34 | ||||
| -rw-r--r-- | src/test/run-pass/class-dtor.rs | 11 |
20 files changed, 216 insertions, 55 deletions
diff --git a/src/librustsyntax/ast.rs b/src/librustsyntax/ast.rs index fb97751fd51..8c27b8ba989 100644 --- a/src/librustsyntax/ast.rs +++ b/src/librustsyntax/ast.rs @@ -669,8 +669,10 @@ enum item_ { item_class([ty_param], /* ty params for class */ [@iface_ref], /* ifaces this class implements */ [@class_member], /* methods, etc. */ - /* (not including ctor) */ + /* (not including ctor or dtor) */ class_ctor, + /* dtor is optional */ + option<class_dtor>, region_param ), item_iface([ty_param], region_param, [ty_method]), @@ -700,6 +702,14 @@ type class_ctor_ = {id: node_id, body: blk}; #[auto_serialize] +type class_dtor = spanned<class_dtor_>; + +#[auto_serialize] +type class_dtor_ = {id: node_id, + self_id: node_id, + body: blk}; + +#[auto_serialize] type native_item = {ident: ident, attrs: [attribute], diff --git a/src/librustsyntax/ast_util.rs b/src/librustsyntax/ast_util.rs index f2cb613f54b..eb442e1ec48 100644 --- a/src/librustsyntax/ast_util.rs +++ b/src/librustsyntax/ast_util.rs @@ -361,6 +361,12 @@ fn operator_prec(op: ast::binop) -> uint { or { 1u } } } + +fn dtor_dec() -> fn_decl { + {inputs: [], output: @{id: 0, node: ty_nil, span: dummy_sp()}, + purity: impure_fn, cf: return_val, constraints: []} +} + // Local Variables: // mode: rust // fill-column: 78; diff --git a/src/librustsyntax/fold.rs b/src/librustsyntax/fold.rs index 7e5a315a1e1..bc1cec9021e 100644 --- a/src/librustsyntax/fold.rs +++ b/src/librustsyntax/fold.rs @@ -274,10 +274,16 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ { fold_ty_params(typms, fld), r) } - item_class(typms, ifaces, items, ctor, rp) { + item_class(typms, ifaces, items, ctor, m_dtor, rp) { let ctor_body = fld.fold_block(ctor.node.body); let ctor_decl = fold_fn_decl(ctor.node.dec, fld); let ctor_id = fld.new_id(ctor.node.id); + let dtor = option::map(m_dtor) {|dtor| + let dtor_body = fld.fold_block(dtor.node.body); + let dtor_id = fld.new_id(dtor.node.id); + {node: {body: dtor_body, + id: dtor_id with dtor.node} + with dtor}}; item_class( typms, vec::map(ifaces, {|p| fold_iface_ref(p, fld) }), @@ -285,8 +291,7 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ { {node: {body: ctor_body, dec: ctor_decl, id: ctor_id with ctor.node} - with ctor}, - rp) + with ctor}, dtor, rp) } item_impl(tps, rp, ifce, ty, methods) { item_impl(fold_ty_params(tps, fld), diff --git a/src/librustsyntax/parse/parser.rs b/src/librustsyntax/parse/parser.rs index 125dbb927f4..7c1e3a85a29 100644 --- a/src/librustsyntax/parse/parser.rs +++ b/src/librustsyntax/parse/parser.rs @@ -1940,14 +1940,24 @@ fn parse_item_class(p: parser) -> item_info { let mut ms: [@class_member] = []; let ctor_id = p.get_id(); let mut the_ctor : option<(fn_decl, blk, codemap::span)> = none; + let mut the_dtor : option<(blk, codemap::span)> = none; while p.token != token::RBRACE { alt parse_class_item(p, class_path) { - ctor_decl(a_fn_decl, blk, s) { - the_ctor = some((a_fn_decl, blk, s)); - } - members(mms) { ms += mms; } + ctor_decl(a_fn_decl, blk, s) { + the_ctor = some((a_fn_decl, blk, s)); + } + dtor_decl(blk, s) { + the_dtor = some((blk, s)); + } + members(mms) { ms += mms; } } } + let actual_dtor = option::map(the_dtor) {|dtor| + let (d_body, d_s) = dtor; + {node: {id: p.get_id(), + self_id: p.get_id(), + body: d_body}, + span: d_s}}; p.bump(); alt the_ctor { some((ct_d, ct_b, ct_s)) { @@ -1957,7 +1967,7 @@ fn parse_item_class(p: parser) -> item_info { self_id: p.get_id(), dec: ct_d, body: ct_b}, - span: ct_s}, rp), + span: ct_s}, actual_dtor, rp), none) } /* @@ -1982,24 +1992,41 @@ fn parse_single_class_item(p: parser, vis: visibility) } } -// lets us identify the constructor declaration at -// parse time +/* + So that we can distinguish a class ctor or dtor + from other class members + */ enum class_contents { ctor_decl(fn_decl, blk, codemap::span), + dtor_decl(blk, codemap::span), members([@class_member]) } +fn parse_ctor(p: parser, result_ty: ast::ty_) -> class_contents { + // Can ctors/dtors have attrs? FIXME + let lo = p.last_span.lo; + let (decl_, _) = parse_fn_decl(p, impure_fn, parse_arg); + let decl = {output: @{id: p.get_id(), + node: result_ty, span: decl_.output.span} + with decl_}; + let body = parse_block(p); + ctor_decl(decl, body, mk_sp(lo, p.last_span.hi)) +} + +fn parse_dtor(p: parser) -> class_contents { + // Can ctors/dtors have attrs? FIXME + let lo = p.last_span.lo; + let body = parse_block(p); + dtor_decl(body, mk_sp(lo, p.last_span.hi)) +} + fn parse_class_item(p:parser, class_name_with_tps: @path) -> class_contents { if eat_keyword(p, "new") { - let lo = p.last_span.lo; - // Can ctors have attrs? - // result type is always the type of the class - let (decl_, _) = parse_fn_decl(p, impure_fn, parse_arg); - let decl = {output: @{id: p.get_id(), - node: ty_path(class_name_with_tps, p.get_id()), - span: decl_.output.span} - with decl_}; - let body = parse_block(p); - ret ctor_decl(decl, body, mk_sp(lo, p.last_span.hi)); + // result type is always the type of the class + ret parse_ctor(p, ty_path(class_name_with_tps, + p.get_id())); + } + else if eat_keyword(p, "drop") { + ret parse_dtor(p); } else if eat_keyword(p, "priv") { expect(p, token::LBRACE); diff --git a/src/librustsyntax/parse/token.rs b/src/librustsyntax/parse/token.rs index 8ee9af1ac4d..07e2d6fa249 100644 --- a/src/librustsyntax/parse/token.rs +++ b/src/librustsyntax/parse/token.rs @@ -261,7 +261,7 @@ fn restricted_keyword_table() -> hashmap<str, ()> { "assert", "be", "break", "check", "claim", "class", "const", "cont", "copy", "crust", - "do", + "do", "drop", "else", "enum", "export", "fail", "false", "fn", "for", "if", "iface", "impl", "import", diff --git a/src/librustsyntax/print/pprust.rs b/src/librustsyntax/print/pprust.rs index 46745b7e28c..5f1f2323b60 100644 --- a/src/librustsyntax/print/pprust.rs +++ b/src/librustsyntax/print/pprust.rs @@ -507,7 +507,7 @@ fn print_item(s: ps, &&item: @ast::item) { bclose(s, item.span); } } - ast::item_class(tps,ifaces,items,ctor, rp) { + ast::item_class(tps, ifaces, items, ctor, m_dtor, rp) { head(s, "class"); word_nbsp(s, item.ident); print_region_param(s, rp); @@ -522,6 +522,11 @@ fn print_item(s: ps, &&item: @ast::item) { print_fn_args_and_ret(s, ctor.node.dec, []); space(s.s); print_block(s, ctor.node.body); + option::iter(m_dtor) {|dtor| + hardbreak_if_not_bol(s); + head(s, "drop"); + print_block(s, dtor.node.body); + } for items.each {|ci| /* FIXME: collect all private items and print them diff --git a/src/librustsyntax/visit.rs b/src/librustsyntax/visit.rs index c9c751900c8..980f9244c35 100644 --- a/src/librustsyntax/visit.rs +++ b/src/librustsyntax/visit.rs @@ -19,7 +19,10 @@ enum fn_kind { fk_anon(proto, capture_clause), //< an anonymous function like fn@(...) fk_fn_block(capture_clause), //< a block {||...} fk_ctor(ident, [ty_param], node_id /* self id */, - def_id /* parent class id */) // class constructor + def_id /* parent class id */), // class constructor + fk_dtor([ty_param], node_id /* self id */, + def_id /* parent class id */) // class destructor + } fn name_of_fn(fk: fn_kind) -> ident { @@ -27,13 +30,14 @@ fn name_of_fn(fk: fn_kind) -> ident { fk_item_fn(name, _) | fk_method(name, _, _) | fk_res(name, _, _) | fk_ctor(name, _, _, _) { name } fk_anon(*) | fk_fn_block(*) { "anon" } + fk_dtor(*) { "drop" } } } fn tps_of_fn(fk: fn_kind) -> [ty_param] { alt fk { fk_item_fn(_, tps) | fk_method(_, tps, _) | fk_res(_, tps, _) - | fk_ctor(_, tps, _, _) { tps } + | fk_ctor(_, tps, _, _) | fk_dtor(tps, _, _) { tps } fk_anon(*) | fk_fn_block(*) { [] } } } @@ -140,7 +144,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) { visit_method_helper(m, e, v) } } - item_class(tps, ifaces, members, ctor, _) { + item_class(tps, ifaces, members, ctor, m_dtor, _) { v.visit_ty_params(tps, e, v); for members.each {|m| v.visit_class_item(m, e, v); @@ -148,6 +152,9 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) { for ifaces.each {|p| visit_path(p.path, e, v); } visit_class_ctor_helper(ctor, i.ident, tps, ast_util::local_def(i.id), e, v); + option::iter(m_dtor) {|dtor| + visit_class_dtor_helper(dtor, tps, + ast_util::local_def(i.id), e, v)}; } item_iface(tps, _rp, methods) { v.visit_ty_params(tps, e, v); @@ -280,12 +287,20 @@ fn visit_method_helper<E>(m: @method, e: E, v: vt<E>) { // Similar logic to the comment on visit_method_helper - Tim fn visit_class_ctor_helper<E>(ctor: class_ctor, nm: ident, tps: [ty_param], parent_id: def_id, e: E, v: vt<E>) { - v.visit_fn(visit::fk_ctor(nm, tps, ctor.node.self_id, + v.visit_fn(fk_ctor(nm, tps, ctor.node.self_id, parent_id), ctor.node.dec, ctor.node.body, ctor.span, ctor.node.id, e, v) } +fn visit_class_dtor_helper<E>(dtor: class_dtor, tps: [ty_param], + parent_id: def_id, e: E, v: vt<E>) { + v.visit_fn(fk_dtor(tps, dtor.node.self_id, + parent_id), ast_util::dtor_dec(), + dtor.node.body, dtor.span, dtor.node.id, e, v) + +} + fn visit_fn<E>(fk: fn_kind, decl: fn_decl, body: blk, _sp: span, _id: node_id, e: E, v: vt<E>) { visit_fn_decl(decl, e, v); diff --git a/src/rustc/metadata/astencode.rs b/src/rustc/metadata/astencode.rs index 080a5431faa..315836fc0c3 100644 --- a/src/rustc/metadata/astencode.rs +++ b/src/rustc/metadata/astencode.rs @@ -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)} diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 7c261829084..3afa3776cca 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -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, diff --git a/src/rustc/middle/ast_map.rs b/src/rustc/middle/ast_map.rs index f2300f9695a..ef5851c3faf 100644 --- a/src/rustc/middle/ast_map.rs +++ b/src/rustc/middle/ast_map.rs @@ -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"] } diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs index 0b86f62eeb9..999c4390487 100644 --- a/src/rustc/middle/kind.rs +++ b/src/rustc/middle/kind.rs @@ -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); diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs index 2635476dfb7..6cdc2724e0c 100644 --- a/src/rustc/middle/region.rs +++ b/src/rustc/middle/region.rs @@ -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} } diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 4461da16a1b..8e9eccf5a0b 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -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| diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 6bad2249cac..0136570a68a 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -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)]; diff --git a/src/rustc/middle/trans/impl.rs b/src/rustc/middle/trans/impl.rs index ec49a0ec7cb..7578b0d1351 100644 --- a/src/rustc/middle/trans/impl.rs +++ b/src/rustc/middle/trans/impl.rs @@ -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) } diff --git a/src/rustc/middle/trans/reachable.rs b/src/rustc/middle/trans/reachable.rs index bd4800c970a..cfae74b8eb1 100644 --- a/src/rustc/middle/trans/reachable.rs +++ b/src/rustc/middle/trans/reachable.rs @@ -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) { diff --git a/src/rustc/middle/tstate/pre_post_conditions.rs b/src/rustc/middle/tstate/pre_post_conditions.rs index 559e8587cef..e5bcec7a46c 100644 --- a/src/rustc/middle/tstate/pre_post_conditions.rs +++ b/src/rustc/middle/tstate/pre_post_conditions.rs @@ -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) { diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 70f32771e00..c4f5c0663d3 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -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}}) diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 6f77fc957b2..8d897161678 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -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); } } diff --git a/src/test/run-pass/class-dtor.rs b/src/test/run-pass/class-dtor.rs new file mode 100644 index 00000000000..8c539cd8328 --- /dev/null +++ b/src/test/run-pass/class-dtor.rs @@ -0,0 +1,11 @@ +class cat { + let done : native fn(uint); + let meows : uint; + new(done: native fn(uint)) { + self.meows = 0u; + self.done = done; + } + drop { self.done(self.meows); } +} + +fn main() {} |
