Skip to content

Commit b5729bd

Browse files
committed
Support attributes on class ctors and dtors
Closes #2660
1 parent cf9a9d1 commit b5729bd

File tree

11 files changed

+109
-51
lines changed

11 files changed

+109
-51
lines changed

src/libsyntax/ast.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,7 @@ type class_ctor = spanned<class_ctor_>;
657657

658658
#[auto_serialize]
659659
type class_ctor_ = {id: node_id,
660+
attrs: ~[attribute],
660661
self_id: node_id,
661662
dec: fn_decl,
662663
body: blk};
@@ -666,6 +667,7 @@ type class_dtor = spanned<class_dtor_>;
666667

667668
#[auto_serialize]
668669
type class_dtor_ = {id: node_id,
670+
attrs: ~[attribute],
669671
self_id: node_id,
670672
body: blk};
671673

src/libsyntax/ast_map.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,9 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
126126
cx.local_id += 1u;
127127
}
128128
alt fk {
129-
visit::fk_ctor(nm, tps, self_id, parent_id) {
129+
visit::fk_ctor(nm, attrs, tps, self_id, parent_id) {
130130
let ct = @{node: {id: id,
131+
attrs: attrs,
131132
self_id: self_id,
132133
dec: /* FIXME (#2543) */ copy decl,
133134
body: /* FIXME (#2543) */ copy body},
@@ -136,16 +137,15 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
136137
/* FIXME (#2543) */ copy tps,
137138
ct, parent_id,
138139
@/* FIXME (#2543) */ copy cx.path));
139-
}
140-
visit::fk_dtor(tps, self_id, parent_id) {
141-
let dt = @{node: {id: id, self_id: self_id,
140+
}
141+
visit::fk_dtor(tps, attrs, self_id, parent_id) {
142+
let dt = @{node: {id: id, attrs: attrs, self_id: self_id,
142143
body: /* FIXME (#2543) */ copy body}, span: sp};
143144
cx.map.insert(id, node_dtor(/* FIXME (#2543) */ copy tps, dt,
144145
parent_id,
145146
@/* FIXME (#2543) */ copy cx.path));
146-
}
147-
148-
_ {}
147+
}
148+
_ {}
149149
}
150150
visit::visit_fn(fk, decl, body, sp, id, cx, v);
151151
}

src/libsyntax/ast_util.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -464,13 +464,13 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
464464
vfn(id);
465465

466466
alt fk {
467-
visit::fk_ctor(nm, tps, self_id, parent_id) {
467+
visit::fk_ctor(nm, _, tps, self_id, parent_id) {
468468
vec::iter(tps, |tp| vfn(tp.id));
469469
vfn(id);
470470
vfn(self_id);
471471
vfn(parent_id.node);
472472
}
473-
visit::fk_dtor(tps, self_id, parent_id) {
473+
visit::fk_dtor(tps, _, self_id, parent_id) {
474474
vec::iter(tps, |tp| vfn(tp.id));
475475
vfn(id);
476476
vfn(self_id);

src/libsyntax/fold.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export wrap;
1616
export fold_ty_param;
1717
export fold_ty_params;
1818
export fold_fn_decl;
19+
export extensions;
1920

2021
iface ast_fold {
2122
fn fold_crate(crate) -> crate;
@@ -701,6 +702,12 @@ impl of ast_fold for ast_fold_precursor {
701702
}
702703
}
703704

705+
impl extensions for ast_fold {
706+
fn fold_attributes(attrs: ~[attribute]) -> ~[attribute] {
707+
attrs.map(|x| fold_attribute_(x, self))
708+
}
709+
}
710+
704711
fn make_fold(afp: ast_fold_precursor) -> ast_fold {
705712
afp as ast_fold
706713
}

src/libsyntax/parse/parser.rs

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ enum pexpr {
9696
So that we can distinguish a class ctor or dtor
9797
from other class members
9898
*/
99-
enum class_contents { ctor_decl(fn_decl, blk, codemap::span),
100-
dtor_decl(blk, codemap::span),
99+
enum class_contents { ctor_decl(fn_decl, ~[attribute], blk, codemap::span),
100+
dtor_decl(blk, ~[attribute], codemap::span),
101101
members(~[@class_member]) }
102102

103103
type arg_or_capture_item = either<arg, capture_item>;
@@ -2145,31 +2145,34 @@ class parser {
21452145
self.expect(token::LBRACE);
21462146
let mut ms: ~[@class_member] = ~[];
21472147
let ctor_id = self.get_id();
2148-
let mut the_ctor : option<(fn_decl, blk, codemap::span)> = none;
2149-
let mut the_dtor : option<(blk, codemap::span)> = none;
2148+
let mut the_ctor : option<(fn_decl, ~[attribute], blk,
2149+
codemap::span)> = none;
2150+
let mut the_dtor : option<(blk, ~[attribute], codemap::span)> = none;
21502151
while self.token != token::RBRACE {
21512152
alt self.parse_class_item(class_path) {
2152-
ctor_decl(a_fn_decl, blk, s) {
2153-
the_ctor = some((a_fn_decl, blk, s));
2153+
ctor_decl(a_fn_decl, attrs, blk, s) {
2154+
the_ctor = some((a_fn_decl, attrs, blk, s));
21542155
}
2155-
dtor_decl(blk, s) {
2156-
the_dtor = some((blk, s));
2156+
dtor_decl(blk, attrs, s) {
2157+
the_dtor = some((blk, attrs, s));
21572158
}
21582159
members(mms) { ms = vec::append(ms, mms); }
21592160
}
21602161
}
21612162
let actual_dtor = do option::map(the_dtor) |dtor| {
2162-
let (d_body, d_s) = dtor;
2163+
let (d_body, d_attrs, d_s) = dtor;
21632164
{node: {id: self.get_id(),
2165+
attrs: d_attrs,
21642166
self_id: self.get_id(),
21652167
body: d_body},
21662168
span: d_s}};
21672169
self.bump();
21682170
alt the_ctor {
2169-
some((ct_d, ct_b, ct_s)) {
2171+
some((ct_d, ct_attrs, ct_b, ct_s)) {
21702172
(class_name,
21712173
item_class(ty_params, traits, ms, {
21722174
node: {id: ctor_id,
2175+
attrs: ct_attrs,
21732176
self_id: self.get_id(),
21742177
dec: ct_d,
21752178
body: ct_b},
@@ -2198,35 +2201,27 @@ class parser {
21982201
}
21992202
}
22002203
2201-
fn parse_ctor(result_ty: ast::ty_) -> class_contents {
2202-
// FIXME (#2660): Can ctors/dtors have attrs?
2204+
fn parse_ctor(attrs: ~[attribute],
2205+
result_ty: ast::ty_) -> class_contents {
22032206
let lo = self.last_span.lo;
22042207
let (decl_, _) = self.parse_fn_decl(impure_fn, |p| p.parse_arg());
22052208
let decl = {output: @{id: self.get_id(),
22062209
node: result_ty, span: decl_.output.span}
22072210
with decl_};
22082211
let body = self.parse_block();
2209-
ctor_decl(decl, body, mk_sp(lo, self.last_span.hi))
2212+
ctor_decl(decl, attrs, body, mk_sp(lo, self.last_span.hi))
22102213
}
22112214
2212-
fn parse_dtor() -> class_contents {
2213-
// FIXME (#2660): Can ctors/dtors have attrs?
2215+
fn parse_dtor(attrs: ~[attribute]) -> class_contents {
22142216
let lo = self.last_span.lo;
22152217
let body = self.parse_block();
2216-
dtor_decl(body, mk_sp(lo, self.last_span.hi))
2218+
dtor_decl(body, attrs, mk_sp(lo, self.last_span.hi))
22172219
}
22182220
22192221
fn parse_class_item(class_name_with_tps: @path)
22202222
-> class_contents {
2221-
if self.eat_keyword(~"new") {
2222-
// result type is always the type of the class
2223-
ret self.parse_ctor(ty_path(class_name_with_tps,
2224-
self.get_id()));
2225-
}
2226-
else if self.eat_keyword(~"drop") {
2227-
ret self.parse_dtor();
2228-
}
2229-
else if self.eat_keyword(~"priv") {
2223+
2224+
if self.eat_keyword(~"priv") {
22302225
self.expect(token::LBRACE);
22312226
let mut results = ~[];
22322227
while self.token != token::RBRACE {
@@ -2235,9 +2230,19 @@ class parser {
22352230
self.bump();
22362231
ret members(results);
22372232
}
2233+
2234+
let attrs = self.parse_outer_attributes();
2235+
2236+
if self.eat_keyword(~"new") {
2237+
// result type is always the type of the class
2238+
ret self.parse_ctor(attrs, ty_path(class_name_with_tps,
2239+
self.get_id()));
2240+
}
2241+
else if self.eat_keyword(~"drop") {
2242+
ret self.parse_dtor(attrs);
2243+
}
22382244
else {
2239-
// Probably need to parse attrs
2240-
ret members(~[self.parse_single_class_item(public)]);
2245+
ret members(~[self.parse_single_class_item(public)]);
22412246
}
22422247
}
22432248

src/libsyntax/print/pprust.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ fn head(s: ps, w: ~str) {
195195
// outer-box is consistent
196196
cbox(s, indent_unit);
197197
// head-box is inconsistent
198-
ibox(s, str::len(w) + 1u);
198+
ibox(s, str::len(w) + 1);
199199
// keyword that starts the head
200200
word_nbsp(s, w);
201201
}
@@ -500,13 +500,19 @@ fn print_item(s: ps, &&item: @ast::item) {
500500
bopen(s);
501501
hardbreak_if_not_bol(s);
502502
maybe_print_comment(s, ctor.span.lo);
503-
head(s, ~"new");
504-
print_fn_args_and_ret(s, ctor.node.dec, ~[]);
503+
print_outer_attributes(s, ctor.node.attrs);
504+
/* Doesn't call head because there shouldn't be a space after new */
505+
cbox(s, indent_unit);
506+
ibox(s, 4);
507+
word(s.s, ~"new(");
508+
print_fn_args(s, ctor.node.dec, ~[]);
509+
word(s.s, ~")");
505510
space(s.s);
506511
print_block(s, ctor.node.body);
507512
do option::iter(m_dtor) |dtor| {
508513
hardbreak_if_not_bol(s);
509514
maybe_print_comment(s, dtor.span.lo);
515+
print_outer_attributes(s, dtor.node.attrs);
510516
head(s, ~"drop");
511517
print_block(s, dtor.node.body);
512518
}

src/libsyntax/visit.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,17 @@ enum fn_kind {
1717
fk_method(ident, ~[ty_param], @method),
1818
fk_anon(proto, capture_clause), //< an anonymous function like fn@(...)
1919
fk_fn_block(capture_clause), //< a block {||...}
20-
fk_ctor(ident, ~[ty_param], node_id /* self id */,
20+
fk_ctor(ident, ~[attribute], ~[ty_param], node_id /* self id */,
2121
def_id /* parent class id */), // class constructor
22-
fk_dtor(~[ty_param], node_id /* self id */,
22+
fk_dtor(~[ty_param], ~[attribute], node_id /* self id */,
2323
def_id /* parent class id */) // class destructor
2424

2525
}
2626

2727
fn name_of_fn(fk: fn_kind) -> ident {
2828
alt fk {
2929
fk_item_fn(name, _) | fk_method(name, _, _)
30-
| fk_ctor(name, _, _, _) { /* FIXME (#2543) */ copy name }
30+
| fk_ctor(name, _, _, _, _) { /* FIXME (#2543) */ copy name }
3131
fk_anon(*) | fk_fn_block(*) { @~"anon" }
3232
fk_dtor(*) { @~"drop" }
3333
}
@@ -36,7 +36,7 @@ fn name_of_fn(fk: fn_kind) -> ident {
3636
fn tps_of_fn(fk: fn_kind) -> ~[ty_param] {
3737
alt fk {
3838
fk_item_fn(_, tps) | fk_method(_, tps, _)
39-
| fk_ctor(_, tps, _, _) | fk_dtor(tps, _, _) {
39+
| fk_ctor(_, _, tps, _, _) | fk_dtor(tps, _, _, _) {
4040
/* FIXME (#2543) */ copy tps
4141
}
4242
fk_anon(*) | fk_fn_block(*) { ~[] }
@@ -271,16 +271,17 @@ fn visit_method_helper<E>(m: @method, e: E, v: vt<E>) {
271271
fn visit_class_ctor_helper<E>(ctor: class_ctor, nm: ident, tps: ~[ty_param],
272272
parent_id: def_id, e: E, v: vt<E>) {
273273
v.visit_fn(fk_ctor(/* FIXME (#2543) */ copy nm,
274+
ctor.node.attrs,
274275
/* FIXME (#2543) */ copy tps,
275-
ctor.node.self_id, parent_id), ctor.node.dec,
276-
ctor.node.body, ctor.span, ctor.node.id, e, v)
276+
ctor.node.self_id, parent_id),
277+
ctor.node.dec, ctor.node.body, ctor.span, ctor.node.id, e, v)
277278

278279
}
279280

280281
fn visit_class_dtor_helper<E>(dtor: class_dtor, tps: ~[ty_param],
281282
parent_id: def_id, e: E, v: vt<E>) {
282-
v.visit_fn(fk_dtor(/* FIXME (#2543) */ copy tps, dtor.node.self_id,
283-
parent_id), ast_util::dtor_dec(),
283+
v.visit_fn(fk_dtor(/* FIXME (#2543) */ copy tps, dtor.node.attrs,
284+
dtor.node.self_id, parent_id), ast_util::dtor_dec(),
284285
dtor.node.body, dtor.span, dtor.node.id, e, v)
285286

286287
}

src/rustc/middle/astencode.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import util::ppaux::ty_to_str;
33
import dvec::extensions;
44
import syntax::ast;
55
import syntax::fold;
6+
import syntax::fold::*;
67
import syntax::visit;
78
import syntax::ast_map;
89
import syntax::ast_util;
@@ -295,21 +296,25 @@ fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item)
295296
}
296297
ast::ii_ctor(ctor, nm, tps, parent_id) {
297298
let ctor_body = fld.fold_block(ctor.node.body);
299+
let ctor_attrs = fld.fold_attributes(ctor.node.attrs);
298300
let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld);
299301
let new_params = fold::fold_ty_params(tps, fld);
300302
let ctor_id = fld.new_id(ctor.node.id);
301303
let new_parent = xcx.tr_def_id(parent_id);
302-
ast::ii_ctor({node: {body: ctor_body, dec: ctor_decl, id: ctor_id
304+
ast::ii_ctor({node: {body: ctor_body, attrs: ctor_attrs,
305+
dec: ctor_decl, id: ctor_id
303306
with ctor.node}
304307
with ctor}, nm, new_params, new_parent)
305308
}
306309
ast::ii_dtor(dtor, nm, tps, parent_id) {
307310
let dtor_body = fld.fold_block(dtor.node.body);
311+
let dtor_attrs = fld.fold_attributes(dtor.node.attrs);
308312
let new_params = fold::fold_ty_params(tps, fld);
309313
let dtor_id = fld.new_id(dtor.node.id);
310314
let new_parent = xcx.tr_def_id(parent_id);
311315
let new_self = fld.new_id(dtor.node.self_id);
312-
ast::ii_dtor({node: {id: dtor_id, self_id: new_self, body: dtor_body}
316+
ast::ii_dtor({node: {id: dtor_id, attrs: dtor_attrs,
317+
self_id: new_self, body: dtor_body}
313318
with dtor},
314319
nm, new_params, new_parent)
315320
}

src/rustc/middle/trans/reachable.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,14 @@ fn traverse_public_item(cx: ctx, item: @item) {
111111
}
112112
item_class(tps, _traits, items, ctor, m_dtor) {
113113
cx.rmap.insert(ctor.node.id, ());
114+
if tps.len() > 0u || attr::find_inline_attr(ctor.node.attrs)
115+
!= attr::ia_none {
116+
traverse_inline_body(cx, ctor.node.body);
117+
}
114118
do option::iter(m_dtor) |dtor| {
115119
cx.rmap.insert(dtor.node.id, ());
116-
// dtors don't have attrs
117-
if tps.len() > 0u {
120+
if tps.len() > 0u || attr::find_inline_attr(dtor.node.attrs)
121+
!= attr::ia_none {
118122
traverse_inline_body(cx, dtor.node.body);
119123
}
120124
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// pp-exact - Make sure we actually print the attributes
2+
3+
class cat {
4+
#[cat_maker]
5+
new(name: ~str) { self.name = name; }
6+
#[cat_dropper]
7+
drop { #error["%s landed on hir feet", self.name]; }
8+
let name: ~str;
9+
}
10+
11+
fn main() { let _kitty = cat(~"Spotty"); }
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class cat {
2+
let name: ~str;
3+
#[cat_maker]
4+
/**
5+
Maybe it should technically be a kitten_maker.
6+
*/
7+
new(name: ~str) { self.name = name; }
8+
#[cat_dropper]
9+
/**
10+
Actually, cats don't always land on their feet when you drop them.
11+
*/
12+
drop { #error("%s landed on hir feet", self.name); }
13+
}
14+
15+
fn main() {
16+
let _kitty = cat(~"Spotty");
17+
}

0 commit comments

Comments
 (0)