From b65dd9d0908ba75ee4cf128058858aea87e4508a Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 3 Aug 2012 15:02:01 -0700 Subject: [PATCH] rustc: Parse, serialize, and deserialize trait inheritance --- src/libsyntax/ast.rs | 2 +- src/libsyntax/ast_map.rs | 10 +++++++++- src/libsyntax/fold.rs | 3 ++- src/libsyntax/parse/parser.rs | 12 +++++++++++- src/libsyntax/print/pprust.rs | 7 ++++++- src/libsyntax/visit.rs | 3 ++- src/rustc/metadata/encoder.rs | 5 ++++- src/rustc/middle/resolve3.rs | 25 +++++++++++++++++++++++-- src/rustc/middle/typeck/check.rs | 4 ++-- src/rustc/middle/typeck/collect.rs | 13 ++++++------- src/rustdoc/attr_pass.rs | 2 +- src/rustdoc/extract.rs | 2 +- src/rustdoc/tystr_pass.rs | 2 +- 13 files changed, 69 insertions(+), 21 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 1b60cb6c47b..34144a9f031 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -724,7 +724,7 @@ enum item_ { /* dtor is optional */ option ), - item_trait(~[ty_param], ~[trait_method]), + item_trait(~[ty_param], ~[@trait_ref], ~[trait_method]), item_impl(~[ty_param], ~[@trait_ref], /* traits this impl implements */ @ty, /* self */ diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index acd20951328..c8daae0982d 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -231,7 +231,15 @@ fn map_item(i: @item, cx: ctx, v: vt) { // only need to handle methods do vec::iter(ms) |m| { map_method(d_id, p, m, cx); } } - item_trait(tps, methods) { + item_trait(tps, traits, methods) { + // Map trait refs to their parent classes. This is + // so we can find the self_ty + for traits.each |p| { + cx.map.insert(p.ref_id, node_item(i, item_path)); + // This is so we can look up the right things when + // encoding/decoding + cx.map.insert(p.impl_id, node_item(i, item_path)); + } for methods.each |tm| { let id = ast_util::trait_method_to_ty_method(tm).id; let d_id = ast_util::local_def(i.id); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index bbf6df468f8..5fa9c584bc4 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -279,8 +279,9 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ { fld.fold_ty(ty), vec::map(methods, |x| fld.fold_method(x))) } - item_trait(tps, methods) { + item_trait(tps, traits, methods) { item_trait(fold_ty_params(tps, fld), + vec::map(traits, |p| fold_trait_ref(p, fld)), /* FIXME (#2543) */ copy methods) } item_mac(m) { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 417d973ee0d..5f2ea6f42f6 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2278,8 +2278,18 @@ class parser { let ident = self.parse_ident(); self.parse_region_param(); let tps = self.parse_ty_params(); + + // Parse traits, if necessary. + let traits; + if self.token == token::COLON { + self.bump(); + traits = self.parse_trait_ref_list(token::LBRACE); + } else { + traits = ~[]; + } + let meths = self.parse_trait_methods(); - (ident, item_trait(tps, meths), none) + (ident, item_trait(tps, traits, meths), none) } // Parses four variants (with the region/type params always optional): diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index feea800b44c..c4b643de8d7 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -590,10 +590,15 @@ fn print_item(s: ps, &&item: @ast::item) { } bclose(s, item.span); } - ast::item_trait(tps, methods) { + ast::item_trait(tps, traits, methods) { head(s, ~"trait"); word(s.s, *item.ident); print_type_params(s, tps); + if vec::len(traits) != 0u { + word_space(s, ~":"); + commasep(s, inconsistent, traits, |s, p| + print_path(s, p.path, false)); + } word(s.s, ~" "); bopen(s); for methods.each |meth| { print_trait_method(s, meth); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index f2159af34e7..61cbba5fc1f 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -162,8 +162,9 @@ fn visit_item(i: @item, e: E, v: vt) { ast_util::local_def(i.id), e, v) }; } - item_trait(tps, methods) { + item_trait(tps, traits, methods) { v.visit_ty_params(tps, e, v); + for traits.each |p| { visit_path(p.path, e, v); } for methods.each |m| { v.visit_trait_method(m, e, v); } diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 256d8e310c4..a5d398c7ad0 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -813,7 +813,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item, vec::append(tps, m.tps)); } } - item_trait(tps, ms) { + item_trait(tps, traits, ms) { add_to_index(); ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); @@ -844,6 +844,9 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item, i += 1u; } encode_path(ebml_w, path, ast_map::path_name(item.ident)); + for traits.each |associated_trait| { + encode_trait_ref(ebml_w, ecx, associated_trait) + } ebml_w.end_tag(); } item_mac(*) { fail ~"item macros unimplemented" } diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs index 243c2af19b2..93173b4008f 100644 --- a/src/rustc/middle/resolve3.rs +++ b/src/rustc/middle/resolve3.rs @@ -988,7 +988,7 @@ class Resolver { visit_item(item, new_parent, visitor); } - item_trait(_, methods) { + item_trait(_, _, methods) { // Add the names of all the methods to the trait info. let method_names = @atom_hashmap(); for methods.each |method| { @@ -3063,7 +3063,7 @@ class Resolver { self_type, methods, visitor); } - item_trait(type_parameters, methods) { + item_trait(type_parameters, traits, methods) { // Create a new rib for the self type. let self_type_rib = @Rib(NormalRibKind); (*self.type_ribs).push(self_type_rib); @@ -3077,6 +3077,27 @@ class Resolver { self.resolve_type_parameters(type_parameters, visitor); + // Resolve derived traits. + for traits.each |trt| { + match self.resolve_path(trt.path, TypeNS, true, + visitor) { + none => + self.session.span_err(trt.path.span, + ~"attempt to derive a \ + nonexistent trait"), + some(def) => { + // Write a mapping from the trait ID to the + // definition of the trait into the definition + // map. + + debug!{"(resolving trait) found trait def: \ + %?", def}; + + self.record_def(trt.ref_id, def); + } + } + } + for methods.each |method| { // Create a new rib for the method-specific type // parameters. diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 91caf75f602..65ad1b26a8d 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -419,7 +419,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) { node_id: it.id }; for ms.each |m| { check_method(ccx, m, self_info);} } - ast::item_trait(_, trait_methods) { + ast::item_trait(_, _, trait_methods) { for trait_methods.each |trait_method| { alt trait_method { required(ty_m) { @@ -434,7 +434,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) { } } } - ast::item_class(tps, traits, members, m_ctor, m_dtor) { + ast::item_class(tps, _, members, m_ctor, m_dtor) { let tcx = ccx.tcx; let class_t = {self_ty: ty::node_id_to_type(tcx, it.id), node_id: it.id}; diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index da9575b898e..ae748b541ff 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -38,20 +38,19 @@ fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) { let substs = {self_r: none, self_ty: none, tps: ~[]}; alt intrinsic_item.node { - - ast::item_trait(_, _) { + ast::item_trait(*) => { let ty = ty::mk_trait(ccx.tcx, def_id, substs); ccx.tcx.intrinsic_defs.insert (intrinsic_item.ident, (def_id, ty)); } - ast::item_enum(_, _) { + ast::item_enum(*) => { let ty = ty::mk_enum(ccx.tcx, def_id, substs); ccx.tcx.intrinsic_defs.insert (intrinsic_item.ident, (def_id, ty)); } - _ { } + _ => {} } } } @@ -147,7 +146,7 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id) { let tcx = ccx.tcx; let rp = tcx.region_paramd_items.contains_key(id); alt check tcx.items.get(id) { - ast_map::node_item(@{node: ast::item_trait(_, ms), _}, _) { + ast_map::node_item(@{node: ast::item_trait(_, _, ms), _}, _) { store_methods::(ccx, id, ms, |m| { alt m { required(ty_m) { @@ -339,7 +338,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) { check_methods_against_trait(ccx, tps, rp, selfty, t, cms); } } - ast::item_trait(tps, trait_methods) { + ast::item_trait(tps, _, trait_methods) { let tpt = ty_of_item(ccx, it); debug!{"item_trait(it.id=%d, tpt.ty=%s)", it.id, ty_to_str(tcx, tpt.ty)}; @@ -550,7 +549,7 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item) tcx.tcache.insert(local_def(it.id), tpt); return tpt; } - ast::item_trait(tps, ms) { + ast::item_trait(tps, _, ms) { let {bounds, substs} = mk_substs(ccx, tps, rp); let t = ty::mk_trait(tcx, local_def(it.id), substs); let tpt = {bounds: bounds, rp: rp, ty: t}; diff --git a/src/rustdoc/attr_pass.rs b/src/rustdoc/attr_pass.rs index a5c41d23574..e22f3a1c9bb 100644 --- a/src/rustdoc/attr_pass.rs +++ b/src/rustdoc/attr_pass.rs @@ -205,7 +205,7 @@ fn merge_method_attrs( let attrs: ~[(~str, option<~str>)] = do astsrv::exec(srv) |ctxt| { alt ctxt.ast_map.get(item_id) { ast_map::node_item(@{ - node: ast::item_trait(_, methods), _ + node: ast::item_trait(_, _, methods), _ }, _) { vec::map(methods, |method| { alt method { diff --git a/src/rustdoc/extract.rs b/src/rustdoc/extract.rs index 0028887d490..a6c653de326 100644 --- a/src/rustdoc/extract.rs +++ b/src/rustdoc/extract.rs @@ -84,7 +84,7 @@ fn moddoc_from_mod( enumdoc_from_enum(itemdoc, variants) )) } - ast::item_trait(_, methods) { + ast::item_trait(_, _, methods) { some(doc::traittag( traitdoc_from_trait(itemdoc, methods) )) diff --git a/src/rustdoc/tystr_pass.rs b/src/rustdoc/tystr_pass.rs index 865a4361aac..ce1f921af27 100644 --- a/src/rustdoc/tystr_pass.rs +++ b/src/rustdoc/tystr_pass.rs @@ -169,7 +169,7 @@ fn get_method_sig( do astsrv::exec(srv) |ctxt| { alt check ctxt.ast_map.get(item_id) { ast_map::node_item(@{ - node: ast::item_trait(_, methods), _ + node: ast::item_trait(_, _, methods), _ }, _) { alt check vec::find(methods, |method| { alt method {