Skip to content

Commit 5428a22

Browse files
committed
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.
1 parent 89cd2f6 commit 5428a22

File tree

20 files changed

+216
-55
lines changed

20 files changed

+216
-55
lines changed

src/librustsyntax/ast.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -669,8 +669,10 @@ enum item_ {
669669
item_class([ty_param], /* ty params for class */
670670
[@iface_ref], /* ifaces this class implements */
671671
[@class_member], /* methods, etc. */
672-
/* (not including ctor) */
672+
/* (not including ctor or dtor) */
673673
class_ctor,
674+
/* dtor is optional */
675+
option<class_dtor>,
674676
region_param
675677
),
676678
item_iface([ty_param], region_param, [ty_method]),
@@ -699,6 +701,14 @@ type class_ctor_ = {id: node_id,
699701
dec: fn_decl,
700702
body: blk};
701703

704+
#[auto_serialize]
705+
type class_dtor = spanned<class_dtor_>;
706+
707+
#[auto_serialize]
708+
type class_dtor_ = {id: node_id,
709+
self_id: node_id,
710+
body: blk};
711+
702712
#[auto_serialize]
703713
type native_item =
704714
{ident: ident,

src/librustsyntax/ast_util.rs

+6
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,12 @@ fn operator_prec(op: ast::binop) -> uint {
361361
or { 1u }
362362
}
363363
}
364+
365+
fn dtor_dec() -> fn_decl {
366+
{inputs: [], output: @{id: 0, node: ty_nil, span: dummy_sp()},
367+
purity: impure_fn, cf: return_val, constraints: []}
368+
}
369+
364370
// Local Variables:
365371
// mode: rust
366372
// fill-column: 78;

src/librustsyntax/fold.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -274,19 +274,24 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
274274
fold_ty_params(typms, fld),
275275
r)
276276
}
277-
item_class(typms, ifaces, items, ctor, rp) {
277+
item_class(typms, ifaces, items, ctor, m_dtor, rp) {
278278
let ctor_body = fld.fold_block(ctor.node.body);
279279
let ctor_decl = fold_fn_decl(ctor.node.dec, fld);
280280
let ctor_id = fld.new_id(ctor.node.id);
281+
let dtor = option::map(m_dtor) {|dtor|
282+
let dtor_body = fld.fold_block(dtor.node.body);
283+
let dtor_id = fld.new_id(dtor.node.id);
284+
{node: {body: dtor_body,
285+
id: dtor_id with dtor.node}
286+
with dtor}};
281287
item_class(
282288
typms,
283289
vec::map(ifaces, {|p| fold_iface_ref(p, fld) }),
284290
vec::map(items, fld.fold_class_item),
285291
{node: {body: ctor_body,
286292
dec: ctor_decl,
287293
id: ctor_id with ctor.node}
288-
with ctor},
289-
rp)
294+
with ctor}, dtor, rp)
290295
}
291296
item_impl(tps, rp, ifce, ty, methods) {
292297
item_impl(fold_ty_params(tps, fld),

src/librustsyntax/parse/parser.rs

+44-17
Original file line numberDiff line numberDiff line change
@@ -1940,14 +1940,24 @@ fn parse_item_class(p: parser) -> item_info {
19401940
let mut ms: [@class_member] = [];
19411941
let ctor_id = p.get_id();
19421942
let mut the_ctor : option<(fn_decl, blk, codemap::span)> = none;
1943+
let mut the_dtor : option<(blk, codemap::span)> = none;
19431944
while p.token != token::RBRACE {
19441945
alt parse_class_item(p, class_path) {
1945-
ctor_decl(a_fn_decl, blk, s) {
1946-
the_ctor = some((a_fn_decl, blk, s));
1947-
}
1948-
members(mms) { ms += mms; }
1946+
ctor_decl(a_fn_decl, blk, s) {
1947+
the_ctor = some((a_fn_decl, blk, s));
1948+
}
1949+
dtor_decl(blk, s) {
1950+
the_dtor = some((blk, s));
1951+
}
1952+
members(mms) { ms += mms; }
19491953
}
19501954
}
1955+
let actual_dtor = option::map(the_dtor) {|dtor|
1956+
let (d_body, d_s) = dtor;
1957+
{node: {id: p.get_id(),
1958+
self_id: p.get_id(),
1959+
body: d_body},
1960+
span: d_s}};
19511961
p.bump();
19521962
alt the_ctor {
19531963
some((ct_d, ct_b, ct_s)) {
@@ -1957,7 +1967,7 @@ fn parse_item_class(p: parser) -> item_info {
19571967
self_id: p.get_id(),
19581968
dec: ct_d,
19591969
body: ct_b},
1960-
span: ct_s}, rp),
1970+
span: ct_s}, actual_dtor, rp),
19611971
none)
19621972
}
19631973
/*
@@ -1982,24 +1992,41 @@ fn parse_single_class_item(p: parser, vis: visibility)
19821992
}
19831993
}
19841994

1985-
// lets us identify the constructor declaration at
1986-
// parse time
1995+
/*
1996+
So that we can distinguish a class ctor or dtor
1997+
from other class members
1998+
*/
19871999
enum class_contents { ctor_decl(fn_decl, blk, codemap::span),
2000+
dtor_decl(blk, codemap::span),
19882001
members([@class_member]) }
19892002

2003+
fn parse_ctor(p: parser, result_ty: ast::ty_) -> class_contents {
2004+
// Can ctors/dtors have attrs? FIXME
2005+
let lo = p.last_span.lo;
2006+
let (decl_, _) = parse_fn_decl(p, impure_fn, parse_arg);
2007+
let decl = {output: @{id: p.get_id(),
2008+
node: result_ty, span: decl_.output.span}
2009+
with decl_};
2010+
let body = parse_block(p);
2011+
ctor_decl(decl, body, mk_sp(lo, p.last_span.hi))
2012+
}
2013+
2014+
fn parse_dtor(p: parser) -> class_contents {
2015+
// Can ctors/dtors have attrs? FIXME
2016+
let lo = p.last_span.lo;
2017+
let body = parse_block(p);
2018+
dtor_decl(body, mk_sp(lo, p.last_span.hi))
2019+
}
2020+
19902021
fn parse_class_item(p:parser, class_name_with_tps: @path)
19912022
-> class_contents {
19922023
if eat_keyword(p, "new") {
1993-
let lo = p.last_span.lo;
1994-
// Can ctors have attrs?
1995-
// result type is always the type of the class
1996-
let (decl_, _) = parse_fn_decl(p, impure_fn, parse_arg);
1997-
let decl = {output: @{id: p.get_id(),
1998-
node: ty_path(class_name_with_tps, p.get_id()),
1999-
span: decl_.output.span}
2000-
with decl_};
2001-
let body = parse_block(p);
2002-
ret ctor_decl(decl, body, mk_sp(lo, p.last_span.hi));
2024+
// result type is always the type of the class
2025+
ret parse_ctor(p, ty_path(class_name_with_tps,
2026+
p.get_id()));
2027+
}
2028+
else if eat_keyword(p, "drop") {
2029+
ret parse_dtor(p);
20032030
}
20042031
else if eat_keyword(p, "priv") {
20052032
expect(p, token::LBRACE);

src/librustsyntax/parse/token.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ fn restricted_keyword_table() -> hashmap<str, ()> {
261261
"assert",
262262
"be", "break",
263263
"check", "claim", "class", "const", "cont", "copy", "crust",
264-
"do",
264+
"do", "drop",
265265
"else", "enum", "export",
266266
"fail", "false", "fn", "for",
267267
"if", "iface", "impl", "import",

src/librustsyntax/print/pprust.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ fn print_item(s: ps, &&item: @ast::item) {
507507
bclose(s, item.span);
508508
}
509509
}
510-
ast::item_class(tps,ifaces,items,ctor, rp) {
510+
ast::item_class(tps, ifaces, items, ctor, m_dtor, rp) {
511511
head(s, "class");
512512
word_nbsp(s, item.ident);
513513
print_region_param(s, rp);
@@ -522,6 +522,11 @@ fn print_item(s: ps, &&item: @ast::item) {
522522
print_fn_args_and_ret(s, ctor.node.dec, []);
523523
space(s.s);
524524
print_block(s, ctor.node.body);
525+
option::iter(m_dtor) {|dtor|
526+
hardbreak_if_not_bol(s);
527+
head(s, "drop");
528+
print_block(s, dtor.node.body);
529+
}
525530
for items.each {|ci|
526531
/*
527532
FIXME: collect all private items and print them

src/librustsyntax/visit.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,25 @@ enum fn_kind {
1919
fk_anon(proto, capture_clause), //< an anonymous function like fn@(...)
2020
fk_fn_block(capture_clause), //< a block {||...}
2121
fk_ctor(ident, [ty_param], node_id /* self id */,
22-
def_id /* parent class id */) // class constructor
22+
def_id /* parent class id */), // class constructor
23+
fk_dtor([ty_param], node_id /* self id */,
24+
def_id /* parent class id */) // class destructor
25+
2326
}
2427

2528
fn name_of_fn(fk: fn_kind) -> ident {
2629
alt fk {
2730
fk_item_fn(name, _) | fk_method(name, _, _) | fk_res(name, _, _)
2831
| fk_ctor(name, _, _, _) { name }
2932
fk_anon(*) | fk_fn_block(*) { "anon" }
33+
fk_dtor(*) { "drop" }
3034
}
3135
}
3236

3337
fn tps_of_fn(fk: fn_kind) -> [ty_param] {
3438
alt fk {
3539
fk_item_fn(_, tps) | fk_method(_, tps, _) | fk_res(_, tps, _)
36-
| fk_ctor(_, tps, _, _) { tps }
40+
| fk_ctor(_, tps, _, _) | fk_dtor(tps, _, _) { tps }
3741
fk_anon(*) | fk_fn_block(*) { [] }
3842
}
3943
}
@@ -140,14 +144,17 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
140144
visit_method_helper(m, e, v)
141145
}
142146
}
143-
item_class(tps, ifaces, members, ctor, _) {
147+
item_class(tps, ifaces, members, ctor, m_dtor, _) {
144148
v.visit_ty_params(tps, e, v);
145149
for members.each {|m|
146150
v.visit_class_item(m, e, v);
147151
}
148152
for ifaces.each {|p| visit_path(p.path, e, v); }
149153
visit_class_ctor_helper(ctor, i.ident, tps,
150154
ast_util::local_def(i.id), e, v);
155+
option::iter(m_dtor) {|dtor|
156+
visit_class_dtor_helper(dtor, tps,
157+
ast_util::local_def(i.id), e, v)};
151158
}
152159
item_iface(tps, _rp, methods) {
153160
v.visit_ty_params(tps, e, v);
@@ -280,12 +287,20 @@ fn visit_method_helper<E>(m: @method, e: E, v: vt<E>) {
280287
// Similar logic to the comment on visit_method_helper - Tim
281288
fn visit_class_ctor_helper<E>(ctor: class_ctor, nm: ident, tps: [ty_param],
282289
parent_id: def_id, e: E, v: vt<E>) {
283-
v.visit_fn(visit::fk_ctor(nm, tps, ctor.node.self_id,
290+
v.visit_fn(fk_ctor(nm, tps, ctor.node.self_id,
284291
parent_id), ctor.node.dec,
285292
ctor.node.body, ctor.span, ctor.node.id, e, v)
286293

287294
}
288295

296+
fn visit_class_dtor_helper<E>(dtor: class_dtor, tps: [ty_param],
297+
parent_id: def_id, e: E, v: vt<E>) {
298+
v.visit_fn(fk_dtor(tps, dtor.node.self_id,
299+
parent_id), ast_util::dtor_dec(),
300+
dtor.node.body, dtor.span, dtor.node.id, e, v)
301+
302+
}
303+
289304
fn visit_fn<E>(fk: fn_kind, decl: fn_decl, body: blk, _sp: span,
290305
_id: node_id, e: E, v: vt<E>) {
291306
visit_fn_decl(decl, e, v);

src/rustc/metadata/astencode.rs

+7
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,13 @@ fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) {
214214
vfn(self_id);
215215
vfn(parent_id.node);
216216
}
217+
// not sure if this should be here? FIXME
218+
visit::fk_dtor(tps, self_id, parent_id) {
219+
vec::iter(tps) {|tp| vfn(tp.id)}
220+
vfn(id);
221+
vfn(self_id);
222+
vfn(parent_id.node);
223+
}
217224
visit::fk_item_fn(_, tps) |
218225
visit::fk_res(_, tps, _) {
219226
vec::iter(tps) {|tp| vfn(tp.id)}

src/rustc/metadata/encoder.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,8 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
187187
encode_def_id(ebml_w, local_def(it.id));
188188
ebml_w.end_tag();
189189
}
190-
item_class(_, _, items, ctor, _) {
190+
// FIXME: I don't *think* dtor needs to be serialized?
191+
item_class(_, _, items, ctor, _dtor, _) {
191192
add_to_index(ebml_w, path, index, it.ident);
192193
ebml_w.start_tag(tag_paths_data_item);
193194
encode_name(ebml_w, it.ident);
@@ -621,7 +622,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
621622
encode_enum_variant_info(ecx, ebml_w, item.id, variants,
622623
path, index, tps);
623624
}
624-
item_class(tps, ifaces, items, ctor, rp) {
625+
// FIXME: not sure if the dtor should be serialized
626+
item_class(tps, ifaces, items, ctor, _dtor, rp) {
625627
/* First, encode the fields and methods
626628
These come first because we need to write them to make
627629
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,
801803
encode_info_for_item(ecx, ebml_w, i, index, *pt);
802804
/* encode ctor, then encode items */
803805
alt i.node {
804-
item_class(tps, _, _, ctor, _) {
806+
// FIXME: not doing anything with dtor
807+
item_class(tps, _, _, ctor, _, _) {
805808
/* this is assuming that ctors aren't inlined...
806809
probably shouldn't assume that */
807810
#debug("encoding info for ctor %s %d", i.ident,

src/rustc/middle/ast_map.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ enum ast_node {
4747
node_local(uint),
4848
// Constructor for either a resource or a class
4949
node_ctor(ident, [ty_param], a_ctor, @path),
50+
// Destructor for a class
51+
node_dtor([ty_param], @class_dtor, def_id, @path),
5052
node_block(blk),
5153
}
5254

@@ -134,6 +136,12 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
134136
cx.map.insert(id, node_ctor(nm, tps, class_ctor(ct, parent_id),
135137
@cx.path));
136138
}
139+
visit::fk_dtor(tps, self_id, parent_id) {
140+
let dt = @{node: {id: id, self_id: self_id, body: body},
141+
span: sp};
142+
cx.map.insert(id, node_dtor(tps, dt, parent_id, @cx.path));
143+
}
144+
137145
_ {}
138146
}
139147
visit::visit_fn(fk, decl, body, sp, id, cx, v);
@@ -204,7 +212,7 @@ fn map_item(i: @item, cx: ctx, v: vt) {
204212
cx.map.insert(nitem.id, node_native_item(nitem, abi, @cx.path));
205213
}
206214
}
207-
item_class(tps, ifces, items, ctor, _) {
215+
item_class(tps, ifces, items, ctor, dtor, _) {
208216
let (_, ms) = ast_util::split_class_items(items);
209217
// Map iface refs to their parent classes. This is
210218
// so we can find the self_ty
@@ -283,9 +291,12 @@ fn node_id_to_str(map: map, id: node_id) -> str {
283291
some(node_local(_)) { // FIXME: add more info here
284292
#fmt["local (id=%?)", id]
285293
}
286-
some(node_ctor(_, _, _, _)) { // FIXME: add more info here
294+
some(node_ctor(*)) { // FIXME: add more info here
287295
#fmt["node_ctor (id=%?)", id]
288296
}
297+
some(node_dtor(*)) { // FIXME: add more info here
298+
#fmt["node_dtor (id=%?)", id]
299+
}
289300
some(node_block(_)) {
290301
#fmt["block"]
291302
}

src/rustc/middle/kind.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
133133
let cap_clause = alt fk {
134134
visit::fk_anon(_, cc) | visit::fk_fn_block(cc) { cc }
135135
visit::fk_item_fn(*) | visit::fk_method(*) |
136-
visit::fk_res(*) | visit::fk_ctor(*) { @[] }
136+
visit::fk_res(*) | visit::fk_ctor(*) | visit::fk_dtor(*) { @[] }
137137
};
138138
let captured_vars = (*cap_clause).map { |cap_item|
139139
let cap_def = cx.tcx.def_map.get(cap_item.id);

src/rustc/middle/region.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ fn resolve_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
375375

376376
let fn_cx = alt fk {
377377
visit::fk_item_fn(*) | visit::fk_method(*) | visit::fk_res(*) |
378-
visit::fk_ctor(*) {
378+
visit::fk_ctor(*) | visit::fk_dtor(*) {
379379
// Top-level functions are a root scope.
380380
{parent: some(id), closure_parent: some(id) with cx}
381381
}

0 commit comments

Comments
 (0)