Skip to content

Commit 7f7f476

Browse files
committed
Implement static typeclass methods. Closes #3132.
1 parent a695e07 commit 7f7f476

20 files changed

+605
-246
lines changed

src/libsyntax/ast.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ type ty_param = {ident: ident, id: node_id, bounds: @~[ty_param_bound]};
7171
#[auto_serialize]
7272
enum def {
7373
def_fn(def_id, purity),
74+
def_static_method(def_id, purity),
7475
def_self(node_id),
7576
def_mod(def_id),
7677
def_foreign_mod(def_id),
@@ -596,6 +597,7 @@ enum ret_style {
596597

597598
#[auto_serialize]
598599
enum self_ty_ {
600+
sty_static, // no self: static method
599601
sty_by_ref, // old by-reference self: ``
600602
sty_value, // by-value self: `self`
601603
sty_region(@region, mutability), // by-region self: `&self`

src/libsyntax/ast_util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ fn variant_def_ids(d: def) -> {enm: def_id, var: def_id} {
5353

5454
pure fn def_id_of_def(d: def) -> def_id {
5555
match d {
56-
def_fn(id, _) | def_mod(id) |
56+
def_fn(id, _) | def_static_method(id, _) | def_mod(id) |
5757
def_foreign_mod(id) | def_const(id) |
5858
def_variant(_, id) | def_ty(id) | def_ty_param(id, _) |
5959
def_use(id) | def_class(id, _) => {

src/libsyntax/parse/parser.rs

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,24 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
4343
match_nonterminal, match_seq, match_tok, method, mode, mt, mul,
4444
mutability, neg, noreturn, not, pat, pat_box, pat_enum,
4545
pat_ident, pat_lit, pat_range, pat_rec, pat_struct, pat_tup,
46-
pat_uniq, pat_wild, path, private, proto, proto_bare,
47-
proto_block, proto_box, proto_uniq, provided, public, pure_fn,
48-
purity, re_anon, re_named, region, rem, required, ret_style,
49-
return_val, self_ty, shl, shr, stmt, stmt_decl, stmt_expr,
50-
stmt_semi, subtract, sty_box, sty_by_ref, sty_region, sty_uniq,
51-
sty_value, token_tree, trait_method, trait_ref, tt_delim, tt_seq,
52-
tt_tok, tt_nonterminal, tuple_variant_kind, ty, ty_, ty_bot,
53-
ty_box, ty_field, ty_fn, ty_infer, ty_mac, ty_method, ty_nil,
54-
ty_param, ty_param_bound, ty_path, ty_ptr, ty_rec, ty_rptr,
55-
ty_tup, ty_u32, ty_uniq, ty_vec, ty_fixed_length, unchecked_blk,
56-
uniq, unsafe_blk, unsafe_fn, variant, view_item, view_item_,
57-
view_item_export, view_item_import, view_item_use, view_path,
58-
view_path_glob, view_path_list, view_path_simple, visibility,
59-
vstore, vstore_box, vstore_fixed, vstore_slice, vstore_uniq};
46+
pat_uniq,
47+
pat_wild, path, private, proto, proto_bare, proto_block,
48+
proto_box, proto_uniq, provided, public, pure_fn, purity,
49+
re_anon, re_named, region, rem, required, ret_style, return_val,
50+
self_ty, shl, shr, stmt, stmt_decl, stmt_expr, stmt_semi,
51+
subtract, sty_box, sty_by_ref, sty_region, sty_static,
52+
sty_uniq, sty_value,
53+
token_tree, trait_method, trait_ref, tt_delim, tt_seq, tt_tok,
54+
tt_nonterminal, ty, ty_, ty_bot, ty_box, ty_field, ty_fn,
55+
ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_param_bound,
56+
ty_path, ty_ptr,
57+
ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq, ty_vec,
58+
ty_fixed_length, tuple_variant_kind,
59+
unchecked_blk, uniq, unsafe_blk, unsafe_fn,
60+
variant, view_item, view_item_, view_item_export,
61+
view_item_import, view_item_use, view_path, view_path_glob,
62+
view_path_list, view_path_simple, visibility, vstore, vstore_box,
63+
vstore_fixed, vstore_slice, vstore_uniq};
6064

6165
export file_type;
6266
export parser;
@@ -279,6 +283,9 @@ class parser {
279283
seq_sep_none()) |p| {
280284
let attrs = p.parse_outer_attributes();
281285
let lo = p.span.lo;
286+
let is_static = p.parse_staticness();
287+
let static_sty = spanned(lo, p.span.hi, sty_static);
288+
282289
let pur = p.parse_fn_purity();
283290
// NB: at the moment, trait methods are public by default; this
284291
// could change.
@@ -287,7 +294,8 @@ class parser {
287294
let tps = p.parse_ty_params();
288295
let d = p.parse_ty_fn_decl(pur);
289296
let hi = p.last_span.hi;
290-
let self_ty = spanned(lo, hi, sty_by_ref); // XXX: Wrong.
297+
let self_ty = if is_static { static_sty } else
298+
{ spanned(lo, hi, sty_by_ref) }; // XXX: Wrong.
291299
debug!{"parse_trait_methods(): trait method signature ends in \
292300
`%s`",
293301
token_to_str(p.reader, p.token)};
@@ -2379,15 +2387,24 @@ class parser {
23792387
23802388
fn parse_method(pr: visibility) -> @method {
23812389
let attrs = self.parse_outer_attributes();
2382-
let lo = self.span.lo, pur = self.parse_fn_purity();
2390+
let lo = self.span.lo;
2391+
2392+
let is_static = self.parse_staticness();
2393+
let static_sty = spanned(lo, self.span.hi, sty_static);
2394+
2395+
let pur = self.parse_fn_purity();
23832396
let ident = self.parse_method_name();
23842397
let tps = self.parse_ty_params();
23852398
let (self_ty, decl, _) = do self.parse_fn_decl_with_self(pur) |p| {
23862399
p.parse_arg()
23872400
};
2401+
// XXX: interaction between staticness, self_ty is broken now
2402+
let self_ty = if is_static { static_sty} else { self_ty };
2403+
23882404
let (inner_attrs, body) = self.parse_inner_attrs_and_block(true);
23892405
let attrs = vec::append(attrs, inner_attrs);
2390-
@{ident: ident, attrs: attrs, tps: tps, self_ty: self_ty, decl: decl,
2406+
@{ident: ident, attrs: attrs,
2407+
tps: tps, self_ty: self_ty, decl: decl,
23912408
body: body, id: self.get_id(), span: mk_sp(lo, body.span.hi),
23922409
self_id: self.get_id(), vis: pr}
23932410
}
@@ -2689,6 +2706,9 @@ class parser {
26892706
else if self.eat_keyword(~"priv") { private }
26902707
else { inherited }
26912708
}
2709+
fn parse_staticness() -> bool {
2710+
self.eat_keyword(~"static")
2711+
}
26922712

26932713
fn parse_mod_items(term: token::token,
26942714
+first_item_attrs: ~[attribute]) -> _mod {

src/libsyntax/print/pprust.rs

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ fn fun_to_str(decl: ast::fn_decl, name: ast::ident,
144144
params: ~[ast::ty_param]) -> ~str {
145145
let buffer = io::mem_buffer();
146146
let s = rust_printer(io::mem_buffer_writer(buffer));
147-
print_fn(s, decl, name, params);
147+
print_fn(s, decl, name, params, none);
148148
end(s); // Close the head box
149149
end(s); // Close the outer box
150150
eof(s.s);
@@ -400,7 +400,7 @@ fn print_type_ex(s: ps, &&ty: @ast::ty, print_colons: bool) {
400400
pclose(s);
401401
}
402402
ast::ty_fn(proto, bounds, d) => {
403-
print_ty_fn(s, some(proto), bounds, d, none, none);
403+
print_ty_fn(s, some(proto), bounds, d, none, none, none);
404404
}
405405
ast::ty_path(path, _) => print_path(s, path, print_colons),
406406
ast::ty_fixed_length(t, v) => {
@@ -425,7 +425,7 @@ fn print_foreign_item(s: ps, item: @ast::foreign_item) {
425425
print_outer_attributes(s, item.attrs);
426426
match item.node {
427427
ast::foreign_item_fn(decl, typarams) => {
428-
print_fn(s, decl, item.ident, typarams);
428+
print_fn(s, decl, item.ident, typarams, none);
429429
end(s); // end head-ibox
430430
word(s.s, ~";");
431431
end(s); // end the outer fn box
@@ -454,7 +454,7 @@ fn print_item(s: ps, &&item: @ast::item) {
454454
455455
}
456456
ast::item_fn(decl, typarams, body) => {
457-
print_fn(s, decl, item.ident, typarams);
457+
print_fn(s, decl, item.ident, typarams, none);
458458
word(s.s, ~" ");
459459
print_block_with_attrs(s, body, item.attrs);
460460
}
@@ -722,7 +722,8 @@ fn print_ty_method(s: ps, m: ast::ty_method) {
722722
hardbreak_if_not_bol(s);
723723
maybe_print_comment(s, m.span.lo);
724724
print_outer_attributes(s, m.attrs);
725-
print_ty_fn(s, none, @~[], m.decl, some(m.ident), some(m.tps));
725+
print_ty_fn(s, none, @~[], m.decl, some(m.ident), some(m.tps),
726+
some(m.self_ty.node));
726727
word(s.s, ~";");
727728
}
728729
@@ -737,7 +738,7 @@ fn print_method(s: ps, meth: @ast::method) {
737738
hardbreak_if_not_bol(s);
738739
maybe_print_comment(s, meth.span.lo);
739740
print_outer_attributes(s, meth.attrs);
740-
print_fn(s, meth.decl, meth.ident, meth.tps);
741+
print_fn(s, meth.decl, meth.ident, meth.tps, some(meth.self_ty.node));
741742
word(s.s, ~" ");
742743
print_block_with_attrs(s, meth.body, meth.attrs);
743744
}
@@ -1150,8 +1151,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
11501151
cbox(s, indent_unit);
11511152
// head-box, will be closed by print-block at start
11521153
ibox(s, 0u);
1153-
print_purity(s, decl.purity);
1154-
word(s.s, proto_to_str(proto));
1154+
word(s.s, fn_header_info_to_str(none, decl.purity, some(proto)));
11551155
print_fn_args_and_ret(s, decl, *cap_clause);
11561156
space(s.s);
11571157
print_block(s, body);
@@ -1455,11 +1455,9 @@ fn print_pat(s: ps, &&pat: @ast::pat) {
14551455
}
14561456

14571457
fn print_fn(s: ps, decl: ast::fn_decl, name: ast::ident,
1458-
typarams: ~[ast::ty_param]) {
1459-
match decl.purity {
1460-
ast::impure_fn => head(s, ~"fn"),
1461-
_ => head(s, purity_to_str(decl.purity) + ~" fn")
1462-
}
1458+
typarams: ~[ast::ty_param],
1459+
opt_self_ty: option<ast::self_ty_>) {
1460+
head(s, fn_header_info_to_str(opt_self_ty, decl.purity, none));
14631461
word(s.s, *name);
14641462
print_type_params(s, typarams);
14651463
print_fn_args_and_ret(s, decl, ~[]);
@@ -1667,9 +1665,10 @@ fn print_arg(s: ps, input: ast::arg) {
16671665
fn print_ty_fn(s: ps, opt_proto: option<ast::proto>,
16681666
bounds: @~[ast::ty_param_bound],
16691667
decl: ast::fn_decl, id: option<ast::ident>,
1670-
tps: option<~[ast::ty_param]>) {
1668+
tps: option<~[ast::ty_param]>,
1669+
opt_self_ty: option<ast::self_ty_>) {
16711670
ibox(s, indent_unit);
1672-
word(s.s, opt_proto_to_str(opt_proto));
1671+
word(s.s, fn_header_info_to_str(opt_self_ty, decl.purity, opt_proto));
16731672
print_bounds(s, bounds);
16741673
match id { some(id) => { word(s.s, ~" "); word(s.s, *id); } _ => () }
16751674
match tps { some(tps) => print_type_params(s, tps), _ => () }
@@ -1869,6 +1868,27 @@ fn next_comment(s: ps) -> option<comments::cmnt> {
18691868
}
18701869
}
18711870

1871+
fn fn_header_info_to_str(opt_sty: option<ast::self_ty_>,
1872+
purity: ast::purity,
1873+
opt_p: option<ast::proto>) -> ~str {
1874+
let mut s = match opt_sty {
1875+
some(ast::sty_static) => ~"static ",
1876+
_ => ~ ""
1877+
};
1878+
1879+
match purity {
1880+
ast::impure_fn => { }
1881+
_ => {
1882+
str::push_str(s, purity_to_str(purity));
1883+
str::push_char(s, ' ');
1884+
}
1885+
}
1886+
1887+
str::push_str(s, opt_proto_to_str(opt_p));
1888+
1889+
return s;
1890+
}
1891+
18721892
fn opt_proto_to_str(opt_p: option<ast::proto>) -> ~str {
18731893
match opt_p {
18741894
none => ~"fn",

src/rustc/metadata/csearch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ fn get_trait_methods(tcx: ty::ctxt, def: ast::def_id) -> @~[ty::method] {
144144
}
145145

146146
fn get_method_names_if_trait(cstore: cstore::cstore, def: ast::def_id)
147-
-> option<@dvec<@~str>> {
147+
-> option<@dvec<(@~str, ast::self_ty_)>> {
148148

149149
let cdata = cstore::get_crate_data(cstore, def.crate);
150150
return decoder::get_method_names_if_trait(cdata, def.node);

src/rustc/metadata/decoder.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,10 @@ fn item_to_def_like(item: ebml::doc, did: ast::def_id, cnum: ast::crate_num)
282282
'u' => dl_def(ast::def_fn(did, ast::unsafe_fn)),
283283
'f' => dl_def(ast::def_fn(did, ast::impure_fn)),
284284
'p' => dl_def(ast::def_fn(did, ast::pure_fn)),
285-
'F' => dl_def(ast::def_fn(did, ast::extern_fn)),
285+
'e' => dl_def(ast::def_fn(did, ast::extern_fn)),
286+
'U' => dl_def(ast::def_static_method(did, ast::unsafe_fn)),
287+
'F' => dl_def(ast::def_static_method(did, ast::impure_fn)),
288+
'P' => dl_def(ast::def_static_method(did, ast::pure_fn)),
286289
'y' => dl_def(ast::def_ty(did)),
287290
't' => dl_def(ast::def_ty(did)),
288291
'm' => dl_def(ast::def_mod(did)),
@@ -592,6 +595,7 @@ fn get_self_ty(item: ebml::doc) -> ast::self_ty_ {
592595

593596
let self_ty_kind = string[0];
594597
match self_ty_kind as char {
598+
's' => { return ast::sty_static; }
595599
'r' => { return ast::sty_by_ref; }
596600
'v' => { return ast::sty_value; }
597601
'@' => { return ast::sty_box(get_mutability(string[1])); }
@@ -693,21 +697,23 @@ fn get_trait_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
693697
@result
694698
}
695699

696-
// If the item in question is a trait, returns its set of methods. Otherwise,
697-
// returns none.
700+
// If the item in question is a trait, returns its set of methods and
701+
// their self types. Otherwise, returns none. This overlaps in an
702+
// annoying way with get_trait_methods.
698703
fn get_method_names_if_trait(cdata: cmd, node_id: ast::node_id)
699-
-> option<@dvec<@~str>> {
704+
-> option<@dvec<(@~str, ast::self_ty_)>> {
700705

701706
let item = lookup_item(node_id, cdata.data);
702707
if item_family(item) != 'I' {
703708
return none;
704709
}
705710

706-
let resulting_method_names = @dvec();
711+
let resulting_methods = @dvec();
707712
for ebml::tagged_docs(item, tag_item_trait_method) |method| {
708-
(*resulting_method_names).push(item_name(method));
713+
resulting_methods.push(
714+
(item_name(method), get_self_ty(method)));
709715
}
710-
return some(resulting_method_names);
716+
return some(resulting_methods);
711717
}
712718

713719
fn get_item_attrs(cdata: cmd,
@@ -757,7 +763,7 @@ fn get_class_fields(cdata: cmd, id: ast::node_id) -> ~[ty::field_ty] {
757763

758764
fn family_has_type_params(fam_ch: char) -> bool {
759765
match check fam_ch {
760-
'c' | 'T' | 'm' | 'n' | 'g' | 'h' | 'j' => false,
766+
'c' | 'T' | 'm' | 'n' | 'g' | 'h' | 'j' | 'e' => false,
761767
'f' | 'u' | 'p' | 'F' | 'U' | 'P' | 'y' | 't' | 'v' | 'i' | 'I' | 'C'
762768
| 'a' | 'S'
763769
=> true
@@ -791,9 +797,10 @@ fn item_family_to_str(fam: char) -> ~str {
791797
'f' => return ~"fn",
792798
'u' => return ~"unsafe fn",
793799
'p' => return ~"pure fn",
794-
'F' => return ~"foreign fn",
795-
'U' => return ~"unsafe foreign fn",
796-
'P' => return ~"pure foreign fn",
800+
'F' => return ~"static method",
801+
'U' => return ~"unsafe static method",
802+
'P' => return ~"pure static method",
803+
'e' => return ~"foreign fn",
797804
'y' => return ~"type",
798805
'T' => return ~"foreign type",
799806
't' => return ~"type",

0 commit comments

Comments
 (0)