Skip to content

Commit fc9c4c3

Browse files
committed
Front-end support for default impls in traits.
1 parent d5563d7 commit fc9c4c3

File tree

14 files changed

+252
-68
lines changed

14 files changed

+252
-68
lines changed

src/libsyntax/ast.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,15 @@ type ty_field = spanned<ty_field_>;
452452
type ty_method = {ident: ident, attrs: ~[attribute],
453453
decl: fn_decl, tps: ~[ty_param], span: span};
454454

455+
#[auto_serialize]
456+
// A trait method is either required (meaning it doesn't have an
457+
// implementation, just a signature) or provided (meaning it has a default
458+
// implementation).
459+
enum trait_method {
460+
required(ty_method),
461+
provided(@method),
462+
}
463+
455464
#[auto_serialize]
456465
enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, }
457466

@@ -695,7 +704,7 @@ enum item_ {
695704
/* dtor is optional */
696705
option<class_dtor>
697706
),
698-
item_trait(~[ty_param], ~[ty_method]),
707+
item_trait(~[ty_param], ~[trait_method]),
699708
item_impl(~[ty_param], option<@trait_ref> /* trait */,
700709
@ty /* self */, ~[@method]),
701710
item_mac(mac),

src/libsyntax/ast_util.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,9 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
511511
visit_ty_method: fn@(_ty_m: ty_method) {
512512
},
513513

514+
visit_trait_method: fn@(_ty_m: trait_method) {
515+
},
516+
514517
visit_class_item: fn@(c: @class_member) {
515518
alt c.node {
516519
instance_var(_, _, _, id,_) {

src/libsyntax/parse/parser.rs

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,14 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
4242
mtc_rep, mtc_tok, mul, mutability, neg, noreturn, not, pat,
4343
pat_box, pat_enum, pat_ident, pat_lit, pat_range, pat_rec,
4444
pat_tup, pat_uniq, pat_wild, path, private, proto, proto_any,
45-
proto_bare, proto_block, proto_box, proto_uniq, public, pure_fn,
46-
purity, re_anon, re_named, region, rem, ret_style,
47-
return_val, shl, shr, stmt, stmt_decl,
48-
stmt_expr, stmt_semi, subtract, token_tree, trait_ref, tt_delim,
49-
tt_dotdotdot, tt_flat, tt_interpolate, ty, ty_, ty_bot, ty_box,
50-
ty_constr, ty_constr_, ty_constr_arg, ty_field, ty_fn, ty_infer,
51-
ty_mac, ty_method, ty_nil, ty_param, ty_path, ty_ptr, ty_rec,
52-
ty_rptr, ty_tup, ty_u32, ty_uniq, ty_vec, ty_vstore,
45+
proto_bare, proto_block, proto_box, proto_uniq, provided, public,
46+
pure_fn, purity, re_anon, re_named, region, rem, required,
47+
ret_style, return_val, shl, shr, stmt, stmt_decl, stmt_expr,
48+
stmt_semi, subtract, token_tree, trait_method, trait_ref,
49+
tt_delim, tt_dotdotdot, tt_flat, tt_interpolate, ty, ty_, ty_bot,
50+
ty_box, ty_constr, ty_constr_, ty_constr_arg, ty_field, ty_fn,
51+
ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_path, ty_ptr,
52+
ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq, ty_vec, ty_vstore,
5353
unchecked_blk, uniq, unsafe_blk, unsafe_fn, variant, view_item,
5454
view_item_, view_item_export, view_item_import, view_item_use,
5555
view_path, view_path_glob, view_path_list, view_path_simple,
@@ -275,7 +275,7 @@ class parser {
275275
constraints: constrs};
276276
}
277277

278-
fn parse_ty_methods() -> ~[ty_method] {
278+
fn parse_trait_methods() -> ~[trait_method] {
279279
do self.parse_unspanned_seq(token::LBRACE, token::RBRACE,
280280
seq_sep_none()) |p| {
281281
let attrs = p.parse_outer_attributes();
@@ -284,12 +284,42 @@ class parser {
284284
let ident = p.parse_method_name();
285285
let tps = p.parse_ty_params();
286286
let d = p.parse_ty_fn_decl(pur), fhi = p.last_span.hi;
287-
self.expect(token::SEMI);
288-
{ident: ident, attrs: attrs, decl: {purity: pur with d}, tps: tps,
289-
span: mk_sp(flo, fhi)}
287+
#debug["parse_trait_methods(): trait method ends in %s",
288+
token_to_str(self.reader, self.token)];
289+
alt self.token {
290+
token::SEMI {
291+
self.bump();
292+
required({ident: ident, attrs: attrs,
293+
decl: {purity: pur with d}, tps: tps,
294+
span: mk_sp(flo, fhi)})
295+
}
296+
token::LBRACE {
297+
self.bump();
298+
let (inner_attrs, body) =
299+
self.parse_inner_attrs_and_block(true);
300+
let attrs = vec::append(attrs, inner_attrs);
301+
self.eat(token::RBRACE);
302+
provided(@{ident: ident,
303+
attrs: attrs,
304+
tps: tps,
305+
decl: d,
306+
body: body,
307+
id: self.get_id(),
308+
span: mk_sp(flo, fhi),
309+
self_id: self.get_id(),
310+
// Provided traits methods always public for now
311+
vis: public})
312+
}
313+
314+
_ { self.fatal("expected ';' or '}` \
315+
but found `"
316+
+ token_to_str(self.reader, self.token) + "`");
317+
}
318+
}
290319
}
291320
}
292321

322+
293323
fn parse_mt() -> mt {
294324
let mutbl = self.parse_mutability();
295325
let t = self.parse_ty(false);
@@ -2127,7 +2157,7 @@ class parser {
21272157
let ident = self.parse_ident();
21282158
self.parse_region_param();
21292159
let tps = self.parse_ty_params();
2130-
let meths = self.parse_ty_methods();
2160+
let meths = self.parse_trait_methods();
21312161
(ident, item_trait(tps, meths), none)
21322162
}
21332163

src/libsyntax/print/pprust.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import pp::{break_offset, word, printer,
55
space, zerobreak, hardbreak, breaks, consistent,
66
inconsistent, eof};
77
import diagnostic;
8+
import ast::{required, provided};
89
import ast_util::operator_prec;
910
import dvec::{dvec, extensions};
1011
import parse::classify::*;
@@ -593,7 +594,7 @@ fn print_item(s: ps, &&item: @ast::item) {
593594
print_type_params(s, tps);
594595
word(s.s, " ");
595596
bopen(s);
596-
for methods.each |meth| { print_ty_method(s, meth); }
597+
for methods.each |meth| { print_trait_method(s, meth); }
597598
bclose(s, item.span);
598599
}
599600
ast::item_mac({node: ast::mac_invoc_tt(pth, tts), _}) {
@@ -647,6 +648,13 @@ fn print_ty_method(s: ps, m: ast::ty_method) {
647648
word(s.s, ";");
648649
}
649650

651+
fn print_trait_method(s: ps, m: ast::trait_method) {
652+
alt m {
653+
required(ty_m) { print_ty_method(s, ty_m) }
654+
provided(m) { print_method(s, m) }
655+
}
656+
}
657+
650658
fn print_method(s: ps, meth: @ast::method) {
651659
hardbreak_if_not_bol(s);
652660
maybe_print_comment(s, meth.span.lo);

src/libsyntax/visit.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ type visitor<E> =
6262
visit_constr: fn@(@path, span, node_id, E, vt<E>),
6363
visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>),
6464
visit_ty_method: fn@(ty_method, E, vt<E>),
65+
visit_trait_method: fn@(trait_method, E, vt<E>),
6566
visit_class_item: fn@(@class_member, E, vt<E>)};
6667

6768
fn default_visitor<E>() -> visitor<E> {
@@ -81,6 +82,7 @@ fn default_visitor<E>() -> visitor<E> {
8182
visit_constr: |a,b,c,d,e|visit_constr::<E>(a, b, c, d, e),
8283
visit_fn: |a,b,c,d,e,f,g|visit_fn::<E>(a, b, c, d, e, f, g),
8384
visit_ty_method: |a,b,c|visit_ty_method::<E>(a, b, c),
85+
visit_trait_method: |a,b,c|visit_trait_method::<E>(a, b, c),
8486
visit_class_item: |a,b,c|visit_class_item::<E>(a, b, c)};
8587
}
8688

@@ -160,7 +162,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
160162
item_trait(tps, methods) {
161163
v.visit_ty_params(tps, e, v);
162164
for methods.each |m| {
163-
v.visit_ty_method(m, e, v);
165+
v.visit_trait_method(m, e, v);
164166
}
165167
}
166168
item_mac(m) { visit_mac(m, e, v) }
@@ -317,6 +319,17 @@ fn visit_ty_method<E>(m: ty_method, e: E, v: vt<E>) {
317319
v.visit_ty(m.decl.output, e, v);
318320
}
319321

322+
fn visit_trait_method<E>(m: trait_method, e: E, v: vt<E>) {
323+
alt m {
324+
required(ty_m) {
325+
v.visit_ty_method(ty_m, e, v)
326+
}
327+
provided(m) {
328+
visit_method_helper(m, e, v)
329+
}
330+
}
331+
}
332+
320333
fn visit_block<E>(b: ast::blk, e: E, v: vt<E>) {
321334
for b.node.view_items.each |vi| { v.visit_view_item(vi, e, v); }
322335
for b.node.stmts.each |s| { v.visit_stmt(s, e, v); }
@@ -465,6 +478,7 @@ type simple_visitor =
465478
visit_constr: fn@(@path, span, node_id),
466479
visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id),
467480
visit_ty_method: fn@(ty_method),
481+
visit_trait_method: fn@(trait_method),
468482
visit_class_item: fn@(@class_member)};
469483

470484
fn simple_ignore_ty(_t: @ty) {}
@@ -487,6 +501,7 @@ fn default_simple_visitor() -> simple_visitor {
487501
visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span,
488502
_id: node_id) { },
489503
visit_ty_method: fn@(_m: ty_method) { },
504+
visit_trait_method: fn@(_m: trait_method) { },
490505
visit_class_item: fn@(_c: @class_member) {}
491506
};
492507
}
@@ -546,6 +561,11 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
546561
f(ty);
547562
visit_ty_method(ty, e, v);
548563
}
564+
fn v_trait_method(f: fn@(trait_method), m: trait_method, &&e: (),
565+
v: vt<()>) {
566+
f(m);
567+
visit_trait_method(m, e, v);
568+
}
549569
fn v_ty_params(f: fn@(~[ty_param]),
550570
ps: ~[ty_param],
551571
&&e: (), v: vt<()>) {
@@ -596,6 +616,8 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
596616
v_fn(v.visit_fn, a, b, c, d, e, f, g),
597617
visit_ty_method: |a,b,c|
598618
v_ty_method(v.visit_ty_method, a, b, c),
619+
visit_trait_method: |a,b,c|
620+
v_trait_method(v.visit_trait_method, a, b, c),
599621
visit_class_item: |a,b,c|
600622
v_class_item(v.visit_class_item, a, b, c)
601623
});

src/rustc/metadata/encoder.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -744,12 +744,21 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
744744
encode_name(ebml_w, item.ident);
745745
let mut i = 0u;
746746
for vec::each(*ty::trait_methods(tcx, local_def(item.id))) |mty| {
747-
ebml_w.start_tag(tag_item_trait_method);
748-
encode_name(ebml_w, mty.ident);
749-
encode_type_param_bounds(ebml_w, ecx, ms[i].tps);
750-
encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
751-
encode_family(ebml_w, purity_fn_family(mty.purity));
752-
ebml_w.end_tag();
747+
alt ms[i] {
748+
required(ty_m) {
749+
ebml_w.start_tag(tag_item_trait_method);
750+
encode_name(ebml_w, mty.ident);
751+
encode_type_param_bounds(ebml_w, ecx, ty_m.tps);
752+
encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
753+
encode_family(ebml_w, purity_fn_family(mty.purity));
754+
ebml_w.end_tag();
755+
}
756+
provided(m) {
757+
encode_info_for_method(ecx, ebml_w, path,
758+
should_inline(m.attrs), item.id,
759+
m, m.tps);
760+
}
761+
}
753762
i += 1u;
754763
}
755764
encode_path(ebml_w, path, ast_map::path_name(item.ident));

src/rustc/middle/resolve.rs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import syntax::{ast, ast_util, codemap, ast_map};
22
import syntax::ast::*;
33
import ast::{ident, fn_ident, def, def_id, node_id};
4+
import ast::{required, provided};
45
import syntax::ast_util::{local_def, def_id_of_def, new_def_hash,
56
class_item_ident, path_to_ident};
67
import pat_util::*;
@@ -566,12 +567,8 @@ fn visit_item_with_scope(e: @env, i: @ast::item,
566567
}
567568
ast::item_trait(tps, methods) {
568569
v.visit_ty_params(tps, sc, v);
569-
let isc = @cons(scope_method(i.id, tps), sc);
570570
for methods.each |m| {
571-
v.visit_ty_params(m.tps, isc, v);
572-
let msc = @cons(scope_method(i.id, vec::append(tps, m.tps)), sc);
573-
for m.decl.inputs.each |a| { v.visit_ty(a.ty, msc, v); }
574-
v.visit_ty(m.decl.output, msc, v);
571+
visit_trait_method(m, i, tps, sc, v);
575572
}
576573
}
577574
ast::item_class(tps, traits, members, ctor, m_dtor) {
@@ -618,6 +615,27 @@ fn visit_item_with_scope(e: @env, i: @ast::item,
618615
e.resolve_unexported = old_resolve_unexported;
619616
}
620617

618+
fn visit_trait_method(m: trait_method, i: @ast::item,
619+
tps: ~[ast::ty_param], sc: scopes,
620+
v: vt<scopes>) {
621+
alt m {
622+
required(ty_m) {
623+
let isc = @cons(scope_method(i.id, tps), sc);
624+
v.visit_ty_params(ty_m.tps, isc, v);
625+
let msc = @cons(scope_method(i.id, vec::append(tps, ty_m.tps)), sc);
626+
for ty_m.decl.inputs.each |a| { v.visit_ty(a.ty, msc, v); }
627+
v.visit_ty(ty_m.decl.output, msc, v);
628+
}
629+
provided(m) {
630+
v.visit_ty_params(m.tps, sc, v);
631+
let msc = @cons(scope_method(m.self_id, vec::append(tps, m.tps)),
632+
sc);
633+
v.visit_fn(visit::fk_method(m.ident, ~[], m),
634+
m.decl, m.body, m.span, m.id, msc, v);
635+
}
636+
}
637+
}
638+
621639
fn visit_foreign_item_with_scope(ni: @ast::foreign_item, &&sc: scopes,
622640
v: vt<scopes>) {
623641
visit::visit_foreign_item(ni, @cons(scope_foreign_item(ni), sc), v);
@@ -1785,7 +1803,16 @@ fn check_item(e: @env, i: @ast::item, &&x: (), v: vt<()>) {
17851803
"type parameter");
17861804
}
17871805
ast::item_trait(_, methods) {
1788-
ensure_unique(*e, i.span, methods, |m| m.ident,
1806+
ensure_unique(*e, i.span, methods, |m| {
1807+
alt m {
1808+
required(ty_m) {
1809+
ty_m.ident
1810+
}
1811+
provided(m) {
1812+
m.ident
1813+
}
1814+
}
1815+
},
17891816
"method");
17901817
}
17911818
ast::item_impl(_, _, _, methods) {

0 commit comments

Comments
 (0)