Skip to content

Commit fd26743

Browse files
committed
Generic classes and generic class methods work cross-crate
Classes can have ty params now. So can methods inside classes. That was probably true before, but now it should still work if you call methods in a class that's defined in a different crate. Yay!
1 parent b2ec26c commit fd26743

File tree

19 files changed

+216
-82
lines changed

19 files changed

+216
-82
lines changed

src/librustsyntax/ast.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ enum item_ {
643643
item_native_mod(native_mod),
644644
item_ty(@ty, [ty_param]),
645645
item_enum([variant], [ty_param]),
646-
item_res(fn_decl /* dtor */, [ty_param], blk,
646+
item_res(fn_decl /* dtor */, [ty_param], blk /* dtor body */,
647647
node_id /* dtor id */, node_id /* ctor id */),
648648
item_class([ty_param], /* ty params for class */
649649
[@class_member], /* methods, etc. */
@@ -703,6 +703,7 @@ enum inlined_item {
703703
ii_item(@item),
704704
ii_method(def_id /* impl id */, @method),
705705
ii_native(@native_item),
706+
ii_ctor(class_ctor, ident, [ty_param], def_id /* parent id */)
706707
}
707708

708709
//

src/librustsyntax/ast_util.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ impl inlined_item_methods for inlined_item {
302302
ii_item(i) { i.ident }
303303
ii_native(i) { i.ident }
304304
ii_method(_, m) { m.ident }
305+
ii_ctor(_, nm, _, _) { nm }
305306
}
306307
}
307308

@@ -310,6 +311,7 @@ impl inlined_item_methods for inlined_item {
310311
ii_item(i) { i.id }
311312
ii_native(i) { i.id }
312313
ii_method(_, m) { m.id }
314+
ii_ctor(ctor, _, _, _) { ctor.node.id }
313315
}
314316
}
315317

@@ -318,6 +320,9 @@ impl inlined_item_methods for inlined_item {
318320
ii_item(i) { v.visit_item(i, e, v) }
319321
ii_native(i) { v.visit_native_item(i, e, v) }
320322
ii_method(_, m) { visit::visit_method_helper(m, e, v) }
323+
ii_ctor(ctor, nm, tps, parent_id) {
324+
visit::visit_class_ctor_helper(ctor, nm, tps, parent_id, e, v);
325+
}
321326
}
322327
}
323328
}

src/librustsyntax/fold.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ export noop_fold_ty;
1414
export noop_fold_block;
1515
export wrap;
1616
export fold_ty_param;
17+
export fold_ty_params;
18+
export fold_fn_decl;
1719

1820
type ast_fold = @mut a_f;
1921

@@ -270,10 +272,12 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
270272
item_class(typms, items, ctor) {
271273
let ctor_body = fld.fold_block(ctor.node.body);
272274
let ctor_decl = fold_fn_decl(ctor.node.dec, fld);
275+
let ctor_id = fld.new_id(ctor.node.id);
273276
item_class(typms,
274277
vec::map(items, fld.fold_class_item),
275278
{node: {body: ctor_body,
276-
dec: ctor_decl with ctor.node}
279+
dec: ctor_decl,
280+
id: ctor_id with ctor.node}
277281
with ctor})
278282
}
279283
item_impl(tps, ifce, ty, methods) {

src/librustsyntax/visit.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,22 @@ enum fn_kind {
1818
fk_res(ident, [ty_param]),
1919
fk_anon(proto), //< an anonymous function like fn@(...)
2020
fk_fn_block, //< a block {||...}
21-
fk_ctor(ident, [ty_param]) // class constructor
21+
fk_ctor(ident, [ty_param], node_id /* self id */,
22+
def_id /* parent class id */) // class constructor
2223
}
2324

2425
fn name_of_fn(fk: fn_kind) -> ident {
2526
alt fk {
2627
fk_item_fn(name, _) | fk_method(name, _, _) | fk_res(name, _)
27-
| fk_ctor(name, _) { name }
28+
| fk_ctor(name, _, _, _) { name }
2829
fk_anon(_) | fk_fn_block { "anon" }
2930
}
3031
}
3132

3233
fn tps_of_fn(fk: fn_kind) -> [ty_param] {
3334
alt fk {
3435
fk_item_fn(_, tps) | fk_method(_, tps, _) | fk_res(_, tps)
35-
| fk_ctor(_, tps) { tps }
36+
| fk_ctor(_, tps, _, _) { tps }
3637
fk_anon(_) | fk_fn_block { [] }
3738
}
3839
}
@@ -141,9 +142,8 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
141142
for members.each {|m|
142143
v.visit_class_item(m, e, v);
143144
}
144-
// make up a fake fn so as to call visit_fn on the ctor
145-
v.visit_fn(fk_ctor(i.ident, tps), ctor.node.dec,
146-
ctor.node.body, ctor.span, ctor.node.id, e, v);
145+
visit_class_ctor_helper(ctor, i.ident, tps,
146+
ast_util::local_def(i.id), e, v);
147147
}
148148
item_iface(tps, methods) {
149149
v.visit_ty_params(tps, e, v);
@@ -270,6 +270,15 @@ fn visit_method_helper<E>(m: @method, e: E, v: vt<E>) {
270270
m.id, e, v);
271271
}
272272

273+
// Similar logic to the comment on visit_method_helper - Tim
274+
fn visit_class_ctor_helper<E>(ctor: class_ctor, nm: ident, tps: [ty_param],
275+
parent_id: def_id, e: E, v: vt<E>) {
276+
v.visit_fn(visit::fk_ctor(nm, tps, ctor.node.self_id,
277+
parent_id), ctor.node.dec,
278+
ctor.node.body, ctor.span, ctor.node.id, e, v)
279+
280+
}
281+
273282
fn visit_fn<E>(fk: fn_kind, decl: fn_decl, body: blk, _sp: span,
274283
_id: node_id, e: E, v: vt<E>) {
275284
visit_fn_decl(decl, e, v);

src/rustc/metadata/astencode.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import util::ppaux::ty_to_str;
2+
13
import syntax::ast;
24
import syntax::fold;
35
import syntax::visit;
@@ -200,8 +202,14 @@ fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) {
200202
vfn(id);
201203

202204
alt fk {
205+
visit::fk_ctor(nm, tps, self_id, parent_id) {
206+
vec::iter(tps) {|tp| vfn(tp.id)}
207+
vfn(id);
208+
vfn(self_id);
209+
vfn(parent_id.node);
210+
}
203211
visit::fk_item_fn(_, tps) |
204-
visit::fk_res(_, tps) | visit::fk_ctor(_, tps) {
212+
visit::fk_res(_, tps) {
205213
vec::iter(tps) {|tp| vfn(tp.id)}
206214
}
207215
visit::fk_method(_, tps, m) {
@@ -376,6 +384,13 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item {
376384
ast::ii_native(i) {
377385
ast::ii_native(fld.fold_native_item(i))
378386
}
387+
ast::ii_ctor(ctor, nm, tps, parent_id) {
388+
let ctor_body = fld.fold_block(ctor.node.body);
389+
let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld);
390+
ast::ii_ctor({node: {body: ctor_body, dec: ctor_decl
391+
with ctor.node}
392+
with ctor}, nm, tps, parent_id)
393+
}
379394
}
380395
}
381396

@@ -403,7 +418,17 @@ fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item)
403418
ast::ii_native(i) {
404419
ast::ii_native(fld.fold_native_item(i))
405420
}
406-
}
421+
ast::ii_ctor(ctor, nm, tps, parent_id) {
422+
let ctor_body = fld.fold_block(ctor.node.body);
423+
let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld);
424+
let new_params = fold::fold_ty_params(tps, fld);
425+
let ctor_id = fld.new_id(ctor.node.id);
426+
let new_parent = xcx.tr_def_id(parent_id);
427+
ast::ii_ctor({node: {body: ctor_body, dec: ctor_decl, id: ctor_id
428+
with ctor.node}
429+
with ctor}, nm, new_params, new_parent)
430+
}
431+
}
407432
}
408433

409434
// ______________________________________________________________________

src/rustc/metadata/encoder.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ fn encode_privacy(ebml_w: ebml::writer, privacy: privacy) {
368368
/* Returns an index of items in this class */
369369
fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
370370
id: node_id, path: ast_map::path,
371+
class_tps: [ty_param],
371372
items: [@class_member],
372373
global_index: @mut[entry<int>])
373374
-> [entry<int>] {
@@ -397,13 +398,10 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
397398
but it works for now -- tjc */
398399
*global_index += [{val: m.id, pos: ebml_w.writer.tell()}];
399400
let impl_path = path + [ast_map::path_name(m.ident)];
400-
/*
401-
Recall methods are (currently) monomorphic, and we don't
402-
repeat the class's ty params in the method decl
403-
*/
404401
#debug("encode_info_for_class: doing %s %d", m.ident, m.id);
405402
encode_info_for_method(ecx, ebml_w, impl_path,
406-
should_inline(m.attrs), id, m, []);
403+
should_inline(m.attrs), id, m,
404+
class_tps + m.tps);
407405
}
408406
_ { /* don't encode private methods */ }
409407
}
@@ -415,7 +413,8 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
415413

416414
fn encode_info_for_fn(ecx: @encode_ctxt, ebml_w: ebml::writer,
417415
id: node_id, ident: ident, path: ast_map::path,
418-
item: option<@item>, tps: [ty_param], decl: fn_decl) {
416+
item: option<inlined_item>, tps: [ty_param],
417+
decl: fn_decl) {
419418
ebml_w.start_tag(tag_items_data_item);
420419
encode_name(ebml_w, ident);
421420
encode_def_id(ebml_w, local_def(id));
@@ -428,7 +427,7 @@ fn encode_info_for_fn(ecx: @encode_ctxt, ebml_w: ebml::writer,
428427
encode_path(ebml_w, path, ast_map::path_name(ident));
429428
alt item {
430429
some(it) {
431-
astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(it));
430+
astencode::encode_inlined_item(ecx, ebml_w, path, it);
432431
}
433432
none {
434433
encode_symbol(ecx, ebml_w, id);
@@ -441,7 +440,7 @@ fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml::writer,
441440
impl_path: ast_map::path, should_inline: bool,
442441
parent_id: node_id,
443442
m: @method, all_tps: [ty_param]) {
444-
#debug("encode_info_for_method: %d %s", m.id, m.ident);
443+
#debug("encode_info_for_method: %d %s %u", m.id, m.ident, all_tps.len());
445444
ebml_w.start_tag(tag_items_data_item);
446445
encode_def_id(ebml_w, local_def(m.id));
447446
encode_family(ebml_w, purity_fn_family(m.decl.purity));
@@ -562,8 +561,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
562561
These come first because we need to write them to make
563562
the index, and the index needs to be in the item for the
564563
class itself */
565-
let idx = encode_info_for_class(ecx, ebml_w, item.id, path, items,
566-
index);
564+
let idx = encode_info_for_class(ecx, ebml_w, item.id, path, tps,
565+
items, index);
567566
/* Index the class*/
568567
add_to_index();
569568
/* Now, make an item for the class itself */
@@ -594,6 +593,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
594593
#debug("Writing %s %d", m.ident, m.id);
595594
encode_family(ebml_w, purity_fn_family(m.decl.purity));
596595
encode_name(ebml_w, m.ident);
596+
encode_type_param_bounds(ebml_w, ecx, tps + m.tps);
597597
encode_type(ecx, ebml_w, node_id_to_type(tcx, m.id));
598598
encode_def_id(ebml_w, local_def(m.id));
599599
ebml_w.end_tag();
@@ -727,7 +727,6 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
727727
alt check ecx.ccx.tcx.items.get(i.id) {
728728
ast_map::node_item(_, pt) {
729729
encode_info_for_item(ecx, ebml_w, i, index, *pt);
730-
/* TODO: encode info for class items! */
731730
/* encode ctor, then encode items */
732731
alt i.node {
733732
item_class(tps,_,ctor) {
@@ -737,7 +736,10 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
737736
ctor.node.id);
738737
*index += [{val: ctor.node.id, pos: ebml_w.writer.tell()}];
739738
encode_info_for_fn(ecx, ebml_w, ctor.node.id, i.ident,
740-
*pt, none, tps, ctor.node.dec)
739+
*pt, if tps.len() > 0u {
740+
some(ii_ctor(ctor, i.ident, tps,
741+
local_def(i.id))) }
742+
else { none }, tps, ctor.node.dec)
741743
}
742744
_ {}
743745
}

src/rustc/middle/ast_map.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,16 @@ enum ast_node {
4444
// order they are introduced.
4545
node_arg(arg, uint),
4646
node_local(uint),
47-
node_ctor(@item, @path),
47+
// Constructor for either a resource or a class
48+
node_ctor(ident, [ty_param], a_ctor, @path),
4849
node_block(blk),
4950
}
5051

52+
enum a_ctor {
53+
res_ctor(fn_decl, node_id, codemap::span),
54+
class_ctor(@class_ctor, def_id /* ID for parent class */),
55+
}
56+
5157
type map = std::map::hashmap<node_id, ast_node>;
5258
type ctx = {map: map, mut path: path,
5359
mut local_id: uint, sess: session};
@@ -99,7 +105,7 @@ fn map_decoded_item(sess: session, map: map, path: path, ii: inlined_item) {
99105
// don't decode and instantiate the impl, but just the method, we have to
100106
// add it to the table now:
101107
alt ii {
102-
ii_item(i) { /* fallthrough */ }
108+
ii_item(_) | ii_ctor(_,_,_,_) { /* fallthrough */ }
103109
ii_native(i) {
104110
cx.map.insert(i.id, node_native_item(i, native_abi_rust_intrinsic,
105111
@path));
@@ -119,6 +125,16 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
119125
cx.map.insert(a.id, node_arg(a, cx.local_id));
120126
cx.local_id += 1u;
121127
}
128+
alt fk {
129+
visit::fk_ctor(nm, tps, self_id, parent_id) {
130+
let ct = @{node: {id: id, self_id: self_id,
131+
dec: decl, body: body},
132+
span: sp};
133+
cx.map.insert(id, node_ctor(nm, tps, class_ctor(ct, parent_id),
134+
@cx.path));
135+
}
136+
_ {}
137+
}
122138
visit::visit_fn(fk, decl, body, sp, id, cx, v);
123139
}
124140

@@ -166,8 +182,10 @@ fn map_item(i: @item, cx: ctx, v: vt) {
166182
map_method(impl_did, extend(cx, i.ident), m, cx);
167183
}
168184
}
169-
item_res(_, _, _, dtor_id, ctor_id) {
170-
cx.map.insert(ctor_id, node_ctor(i, item_path));
185+
item_res(decl, tps, _, dtor_id, ctor_id) {
186+
cx.map.insert(ctor_id, node_ctor(i.ident, tps,
187+
res_ctor(decl, ctor_id, i.span),
188+
item_path));
171189
cx.map.insert(dtor_id, node_item(i, item_path));
172190
}
173191
item_enum(vs, _) {
@@ -186,7 +204,6 @@ fn map_item(i: @item, cx: ctx, v: vt) {
186204
}
187205
}
188206
item_class(_, items, ctor) {
189-
cx.map.insert(ctor.node.id, node_ctor(i, item_path));
190207
let d_id = ast_util::local_def(i.id);
191208
let p = extend(cx, i.ident);
192209
for items.each {|ci|
@@ -267,7 +284,7 @@ fn node_id_to_str(map: map, id: node_id) -> str {
267284
some(node_local(_)) { // FIXME: add more info here
268285
#fmt["local (id=%?)", id]
269286
}
270-
some(node_ctor(_, _)) { // FIXME: add more info here
287+
some(node_ctor(_, _, _, _)) { // FIXME: add more info here
271288
#fmt["node_ctor (id=%?)", id]
272289
}
273290
some(node_block(_)) {

src/rustc/middle/mutbl.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -214,15 +214,15 @@ fn visit_expr(ex: @expr, &&cx: @ctx, v: visit::vt<@ctx>) {
214214

215215
fn visit_item(item: @item, &&cx: @ctx, v: visit::vt<@ctx>) {
216216
alt item.node {
217-
item_class(tps, items, ctor) {
218-
v.visit_ty_params(tps, cx, v);
219-
vec::map::<@class_member, ()>(items,
220-
{|i| v.visit_class_item(i, cx, v); });
221-
v.visit_fn(visit::fk_ctor(item.ident, tps), ctor.node.dec,
222-
ctor.node.body, ctor.span, ctor.node.id,
223-
@{in_ctor: some(ctor.node.self_id) with *cx}, v);
224-
}
225-
_ { visit::visit_item(item, cx, v); }
217+
item_class(tps, items, ctor) {
218+
v.visit_ty_params(tps, cx, v);
219+
vec::map::<@class_member, ()>(items,
220+
{|i| v.visit_class_item(i, cx, v); });
221+
visit::visit_class_ctor_helper(ctor, item.ident, tps,
222+
ast_util::local_def(item.id),
223+
@{in_ctor: some(ctor.node.self_id) with *cx}, v);
224+
}
225+
_ { visit::visit_item(item, cx, v); }
226226
}
227227
}
228228

src/rustc/middle/resolve.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ fn visit_fn_with_scope(e: @env, fk: visit::fn_kind, decl: ast::fn_decl,
572572
for decl.constraints.each {|c| resolve_constr(e, c, sc, v); }
573573
let scope = alt fk {
574574
visit::fk_item_fn(_, tps) | visit::fk_res(_, tps) |
575-
visit::fk_method(_, tps, _) | visit::fk_ctor(_, tps)
575+
visit::fk_method(_, tps, _) | visit::fk_ctor(_, tps, _, _)
576576
{ scope_bare_fn(decl, id, tps) }
577577
visit::fk_anon(ast::proto_bare) { scope_bare_fn(decl, id, []) }
578578
visit::fk_anon(_) | visit::fk_fn_block { scope_fn_expr(decl, id, []) }

0 commit comments

Comments
 (0)