Skip to content

Commit 30c272c

Browse files
committed
methods work
Cross-crate method calls don't work yet. Added run-pass/class-method-cross-crate to test that, but it's xfailed References to fields within methods don't work yet. Added run-pass/class-methods to test that, but it's also xfailed
1 parent 3e47442 commit 30c272c

File tree

10 files changed

+162
-39
lines changed

10 files changed

+162
-39
lines changed

src/rustc/metadata/csearch.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import std::map::hashmap;
1313

1414
export get_symbol;
1515
export get_class_fields;
16+
// export get_class_method_ids;
1617
export get_field_type;
1718
export get_type_param_count;
1819
export lookup_defs;
@@ -127,9 +128,17 @@ fn get_iface_methods(tcx: ty::ctxt, def: ast::def_id) -> @[ty::method] {
127128
fn get_class_fields(tcx: ty::ctxt, def: ast::def_id) -> [ty::field_ty] {
128129
let cstore = tcx.sess.cstore;
129130
let cdata = cstore::get_crate_data(cstore, def.crate);
130-
decoder::get_class_fields(tcx, cdata, def.node)
131+
decoder::get_class_fields(cdata, def.node)
131132
}
132133

134+
/*
135+
fn get_class_method_ids(tcx: ty::ctxt, def: ast::def_id) -> [ty::field_ty] {
136+
let cstore = tcx.sess.cstore;
137+
let cdata = cstore::get_crate_data(cstore, def.crate);
138+
decoder::get_class_method_ids(cdata, def.node)
139+
}
140+
*/
141+
133142
fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty {
134143
let cstore = tcx.sess.cstore;
135144
let cdata = cstore::get_crate_data(cstore, def.crate);

src/rustc/metadata/decoder.rs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import middle::trans::common::maps;
1717
import util::ppaux::ty_to_str;
1818

1919
export get_class_fields;
20+
// export get_class_method_ids;
2021
export get_symbol;
2122
export get_enum_variants;
2223
export get_type;
@@ -113,7 +114,7 @@ fn item_parent_item(d: ebml::doc) -> option<ast::def_id> {
113114
found
114115
}
115116

116-
fn class_field_id(d: ebml::doc, cdata: cmd) -> ast::def_id {
117+
fn class_member_id(d: ebml::doc, cdata: cmd) -> ast::def_id {
117118
let tagdoc = ebml::get_doc(d, tag_def_id);
118119
ret translate_def_id(cdata, parse_def_id(ebml::doc_data(tagdoc)));
119120
}
@@ -408,27 +409,36 @@ fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
408409
@result
409410
}
410411

411-
/* Take a node ID for a class, return a vector of the class's
412-
field names/IDs */
413-
fn get_class_fields(tcx: ty::ctxt,
414-
cdata: cmd, id: ast::node_id) -> [ty::field_ty] {
412+
// Helper function that gets either fields or methods
413+
fn get_class_members(cdata: cmd, id: ast::node_id,
414+
family: char) -> [ty::field_ty] {
415415
let data = cdata.data;
416416
let item = lookup_item(id, data), result = [];
417417
ebml::tagged_docs(item, tag_items_data_item) {|an_item|
418-
let fam = item_family(an_item);
419-
alt fam {
420-
'g' {
421-
let name = item_name(an_item);
422-
let _ty = doc_type(an_item, tcx, cdata);
423-
let did = class_field_id(an_item, cdata);
424-
result += [{ident: name, id: did}];
425-
}
426-
_ { /* this only handles fields */}
418+
if item_family(an_item) == family {
419+
let name = item_name(an_item);
420+
let did = class_member_id(an_item, cdata);
421+
result += [{ident: name, id: did}];
427422
}
428423
}
429424
result
430425
}
431426

427+
428+
/* Take a node ID for a class, return a vector of the class's
429+
field names/IDs */
430+
fn get_class_fields(cdata: cmd, id: ast::node_id) -> [ty::field_ty] {
431+
get_class_members(cdata, id, 'g')
432+
}
433+
434+
/*
435+
/* Take a node ID for a class, return a vector of the class's
436+
method names/IDs */
437+
fn get_class_method_ids(cdata: cmd, id: ast::node_id) -> [ty::field_ty] {
438+
get_class_members(cdata, id, 'h')
439+
}
440+
*/
441+
432442
fn family_has_type_params(fam_ch: char) -> bool {
433443
alt check fam_ch {
434444
'c' | 'T' | 'm' | 'n' | 'g' | 'h' { false }

src/rustc/middle/trans/base.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4194,7 +4194,10 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
41944194
trans_fn(ccx, *path + [path_name(item.ident)], ctor.node.dec,
41954195
ctor_body__, llctor_decl, no_self,
41964196
none, ctor.node.id, some(rslt_expr));
4197-
// TODO: translate methods!
4197+
// Translate methods
4198+
let (_, ms) = ast_util::split_class_items(items);
4199+
// not sure how this is going to work what with "self" and fields
4200+
impl::trans_impl(ccx, *path, item.ident, ms, tps);
41984201
}
41994202
_ {/* fall through */ }
42004203
}

src/rustc/middle/ty.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import session::session;
66
import syntax::ast;
77
import syntax::ast::*;
88
import syntax::ast_util;
9+
import syntax::ast_util::{is_local, split_class_items};
910
import syntax::codemap::span;
1011
import metadata::csearch;
1112
import util::common::*;
@@ -41,6 +42,7 @@ export get_element_type;
4142
export is_binopable;
4243
export is_pred_ty;
4344
export lookup_class_fields;
45+
export lookup_class_method_by_name;
4446
export lookup_field_type;
4547
export lookup_item_type;
4648
export method;
@@ -2523,7 +2525,7 @@ fn lookup_field_type(tcx: ctxt, class_id: def_id, id: def_id) -> ty::t {
25232525
}
25242526
}
25252527

2526-
// Look up the list of item types for a given class
2528+
// Look up the list of field names and IDs for a given class
25272529
// Fails if the id is not bound to a class.
25282530
fn lookup_class_fields(cx: ctxt, did: ast::def_id) -> [field_ty] {
25292531
if did.crate == ast::local_crate {
@@ -2544,7 +2546,41 @@ fn lookup_class_fields(cx: ctxt, did: ast::def_id) -> [field_ty] {
25442546
}
25452547
}
25462548

2547-
// must be called after typechecking?
2549+
// Look up the list of method names and IDs for a given class
2550+
// Fails if the id is not bound to a class.
2551+
fn lookup_class_method_ids(cx: ctxt, did: ast::def_id)
2552+
: is_local(did) -> [{name: ident, id: node_id}] {
2553+
alt cx.items.find(did.node) {
2554+
some(ast_map::node_item(@{node: item_class(_,items,_), _}, _)) {
2555+
let (_,ms) = split_class_items(items);
2556+
vec::map(ms, {|m| {name: m.ident, id: m.id}})
2557+
}
2558+
_ {
2559+
cx.sess.bug("lookup_class_method_ids: id not bound to a class");
2560+
}
2561+
}
2562+
}
2563+
2564+
/* Given a class def_id and a method name, return the method's
2565+
def_id. Needed so we can do static dispatch for methods */
2566+
fn lookup_class_method_by_name(cx:ctxt, did: ast::def_id, name: ident,
2567+
sp: span) ->
2568+
def_id {
2569+
if check is_local(did) {
2570+
let ms = lookup_class_method_ids(cx, did);
2571+
for m in ms {
2572+
if m.name == name {
2573+
ret ast_util::local_def(m.id);
2574+
}
2575+
}
2576+
cx.sess.span_fatal(sp, #fmt("Class doesn't have a method named %s",
2577+
name));
2578+
}
2579+
else {
2580+
csearch::get_impl_method(cx.sess.cstore, did, name)
2581+
}
2582+
}
2583+
25482584
fn class_field_tys(items: [@class_item]) -> [field_ty] {
25492585
let rslt = [];
25502586
for it in items {

src/rustc/middle/typeck.rs

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -893,11 +893,20 @@ mod collect {
893893
}
894894
}
895895
fn ensure_iface_methods(tcx: ty::ctxt, id: ast::node_id) {
896+
fn store_methods<T>(tcx: ty::ctxt, id: ast::node_id,
897+
stuff: [T], f: fn@(T) -> ty::method) {
898+
ty::store_iface_methods(tcx, id, @vec::map(stuff, f));
899+
}
900+
896901
alt check tcx.items.get(id) {
897902
ast_map::node_item(@{node: ast::item_iface(_, ms), _}, _) {
898-
ty::store_iface_methods(tcx, id, @vec::map(ms, {|m|
899-
ty_of_ty_method(tcx, m_collect, m)
900-
}));
903+
store_methods::<ast::ty_method>(tcx, id, ms, {|m|
904+
ty_of_ty_method(tcx, m_collect, m)});
905+
}
906+
ast_map::node_item(@{node: ast::item_class(_,its,_), _}, _) {
907+
let (_,ms) = split_class_items(its);
908+
store_methods::<@ast::method>(tcx, id, ms, {|m|
909+
ty_of_method(tcx, m_collect, m)});
901910
}
902911
}
903912
}
@@ -1038,13 +1047,17 @@ mod collect {
10381047
write_ty(tcx, ctor.node.id, t_ctor);
10391048
tcx.tcache.insert(local_def(ctor.node.id),
10401049
{bounds: tpt.bounds, ty: t_ctor});
1050+
ensure_iface_methods(tcx, it.id);
10411051
/* FIXME: check for proper public/privateness */
10421052
// Write the type of each of the members
10431053
let (fields, methods) = split_class_items(members);
10441054
for f in fields {
10451055
convert_class_item(tcx, f);
10461056
}
1047-
convert_methods(tcx, methods, @[], none);
1057+
let selfty = ty::mk_class(tcx, local_def(it.id),
1058+
mk_ty_params(tcx, tps).params);
1059+
// The selfty is just the class type
1060+
convert_methods(tcx, methods, @[], some(selfty));
10481061
}
10491062
_ {
10501063
// This call populates the type cache with the converted type
@@ -1854,13 +1867,13 @@ fn lookup_method(fcx: @fn_ctxt, expr: @ast::expr, node_id: ast::node_id,
18541867
}
18551868
}
18561869

1857-
enum method_parent {
1858-
cls(ast::def_id),
1870+
enum method_kind {
1871+
cls(ast::def_id), // *method* id (in both cases)
18591872
an_iface(ast::def_id)
18601873
}
18611874

18621875
fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method],
1863-
tps: [ty::t], parent: method_parent, name: ast::ident, sp: span)
1876+
tps: [ty::t], parent: method_kind, name: ast::ident, sp: span)
18641877
-> option<{method_ty: ty::t, n_tps: uint, substs: [ty::t],
18651878
origin: method_origin, self_sub: option<self_subst>}> {
18661879
#debug("lookup_method_inner_: %? %? %s", ms, parent, name);
@@ -1878,13 +1891,19 @@ fn lookup_method_inner_(tcx: ty::ctxt, ms: [ty::method],
18781891
boxed iface");
18791892
}
18801893
ret some({method_ty: fty,
1881-
n_tps: vec::len(*m.tps),
1882-
substs: tps,
1883-
origin: alt parent {
1884-
cls(did) { method_static(did) }
1885-
an_iface(did) { method_iface(did, i) }
1886-
},
1887-
self_sub: none});
1894+
n_tps: vec::len(*m.tps),
1895+
substs: tps,
1896+
origin: alt parent {
1897+
cls(parent_id) {
1898+
// look up method named <name>
1899+
// its id is did
1900+
let m_declared = ty::lookup_class_method_by_name(tcx,
1901+
parent_id, name, sp);
1902+
method_static(m_declared)
1903+
}
1904+
an_iface(did) { method_iface(did, i) }
1905+
},
1906+
self_sub: none});
18881907
}
18891908
i += 1u;
18901909
}

src/rustc/syntax/ast_util.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ fn path_name(p: @path) -> str { path_name_i(p.node.idents) }
1717

1818
fn path_name_i(idents: [ident]) -> str { str::connect(idents, "::") }
1919

20-
fn local_def(id: node_id) -> def_id { ret {crate: local_crate, node: id}; }
20+
fn local_def(id: node_id) -> def_id { {crate: local_crate, node: id} }
21+
22+
pure fn is_local(did: ast::def_id) -> bool { did.crate == local_crate }
2123

2224
fn stmt_id(s: stmt) -> node_id {
2325
alt s.node {

src/test/auxiliary/cci_class_2.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
mod kitties {
2+
3+
class cat {
4+
priv {
5+
let mutable meows : uint;
6+
}
7+
8+
let how_hungry : int;
9+
10+
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
11+
12+
fn speak() {}
13+
}
14+
15+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// xfail-test
2+
// xfail-fast
3+
// aux-build:cci_class_2.rs
4+
use cci_class;
5+
import cci_class::kitties::*;
6+
7+
fn main() {
8+
let nyan : cat = cat(52u, 99);
9+
let kitty = cat(1000u, 2);
10+
assert(nyan.how_hungry == 99);
11+
assert(kitty.how_hungry == 2);
12+
nyan.speak();
13+
}

src/test/run-pass/class-methods.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// xfail-test
2+
class cat {
3+
priv {
4+
let mutable meows : uint;
5+
}
6+
7+
let how_hungry : int;
8+
9+
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
10+
11+
fn speak() { meows += 1u; }
12+
fn meow_count() -> uint { meows }
13+
}
14+
15+
fn main() {
16+
let nyan : cat = cat(52u, 99);
17+
let kitty = cat(1000u, 2);
18+
assert(nyan.how_hungry == 99);
19+
assert(kitty.how_hungry == 2);
20+
nyan.speak();
21+
assert(nyan.meow_count() == 53u);
22+
}
Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// xfail-test
21
class cat {
32
priv {
43
let mutable meows : uint;
@@ -9,10 +8,6 @@ class cat {
98
new(in_x : uint, in_y : int) { meows = in_x; how_hungry = in_y; }
109

1110
fn speak() {}
12-
/*
13-
fn speak() { meows += 1u; }
14-
fn meow_count() -> uint { meows }
15-
*/
1611
}
1712

1813
fn main() {
@@ -21,5 +16,4 @@ fn main() {
2116
assert(nyan.how_hungry == 99);
2217
assert(kitty.how_hungry == 2);
2318
nyan.speak();
24-
// assert(nyan.meow_count() == 53u);
2519
}

0 commit comments

Comments
 (0)