about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorLindsey Kuper <lindsey@rockstargirl.org>2012-07-10 13:44:20 -0700
committerLindsey Kuper <lindsey@rockstargirl.org>2012-07-13 11:16:07 -0700
commitfc9c4c32451dadab4f8a81897e8fc83ae6473d95 (patch)
treed54e7d2d8ecce561fb04375e31516ccaf1521aa0 /src
parentd5563d732dfb4ebbf50ad221d8d4568319210a65 (diff)
Front-end support for default impls in traits.
Diffstat (limited to 'src')
-rw-r--r--src/libsyntax/ast.rs11
-rw-r--r--src/libsyntax/ast_util.rs3
-rw-r--r--src/libsyntax/parse/parser.rs56
-rw-r--r--src/libsyntax/print/pprust.rs10
-rw-r--r--src/libsyntax/visit.rs24
-rw-r--r--src/rustc/metadata/encoder.rs21
-rw-r--r--src/rustc/middle/resolve.rs39
-rw-r--r--src/rustc/middle/resolve3.rs69
-rw-r--r--src/rustc/middle/typeck.rs1
-rw-r--r--src/rustc/middle/typeck/collect.rs11
-rw-r--r--src/rustdoc/attr_pass.rs9
-rw-r--r--src/rustdoc/doc.rs8
-rw-r--r--src/rustdoc/extract.rs32
-rw-r--r--src/rustdoc/tystr_pass.rs26
14 files changed, 252 insertions, 68 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index e79e5e2ab77..f79f6cbcae2 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -453,6 +453,15 @@ type ty_method = {ident: ident, attrs: ~[attribute],
                   decl: fn_decl, tps: ~[ty_param], span: span};
 
 #[auto_serialize]
+// A trait method is either required (meaning it doesn't have an
+// implementation, just a signature) or provided (meaning it has a default
+// implementation).
+enum trait_method {
+    required(ty_method),
+    provided(@method),
+}
+
+#[auto_serialize]
 enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, }
 
 #[auto_serialize]
@@ -695,7 +704,7 @@ enum item_ {
                /* dtor is optional */
                option<class_dtor>
                ),
-    item_trait(~[ty_param], ~[ty_method]),
+    item_trait(~[ty_param], ~[trait_method]),
     item_impl(~[ty_param], option<@trait_ref> /* trait */,
               @ty /* self */, ~[@method]),
     item_mac(mac),
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 1e2de4f5bfa..5675ecadf62 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -511,6 +511,9 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
         visit_ty_method: fn@(_ty_m: ty_method) {
         },
 
+        visit_trait_method: fn@(_ty_m: trait_method) {
+        },
+
         visit_class_item: fn@(c: @class_member) {
             alt c.node {
               instance_var(_, _, _, id,_) {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index e1f3eb3217c..5a1eb7636ba 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -42,14 +42,14 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
              mtc_rep, mtc_tok, mul, mutability, neg, noreturn, not, pat,
              pat_box, pat_enum, pat_ident, pat_lit, pat_range, pat_rec,
              pat_tup, pat_uniq, pat_wild, path, private, proto, proto_any,
-             proto_bare, proto_block, proto_box, proto_uniq, public, pure_fn,
-             purity, re_anon, re_named, region, rem, ret_style,
-             return_val, shl, shr, stmt, stmt_decl,
-             stmt_expr, stmt_semi, subtract, token_tree, trait_ref, tt_delim,
-             tt_dotdotdot, tt_flat, tt_interpolate, ty, ty_, ty_bot, ty_box,
-             ty_constr, ty_constr_, ty_constr_arg, ty_field, ty_fn, ty_infer,
-             ty_mac, ty_method, ty_nil, ty_param, ty_path, ty_ptr, ty_rec,
-             ty_rptr, ty_tup, ty_u32, ty_uniq, ty_vec, ty_vstore,
+             proto_bare, proto_block, proto_box, proto_uniq, provided, public,
+             pure_fn, purity, re_anon, re_named, region, rem, required,
+             ret_style, return_val, shl, shr, stmt, stmt_decl, stmt_expr,
+             stmt_semi, subtract, token_tree, trait_method, trait_ref,
+             tt_delim, tt_dotdotdot, tt_flat, tt_interpolate, ty, ty_, ty_bot,
+             ty_box, ty_constr, ty_constr_, ty_constr_arg, ty_field, ty_fn,
+             ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_path, ty_ptr,
+             ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq, ty_vec, ty_vstore,
              unchecked_blk, uniq, unsafe_blk, unsafe_fn, variant, view_item,
              view_item_, view_item_export, view_item_import, view_item_use,
              view_path, view_path_glob, view_path_list, view_path_simple,
@@ -275,7 +275,7 @@ class parser {
              constraints: constrs};
     }
 
-    fn parse_ty_methods() -> ~[ty_method] {
+    fn parse_trait_methods() -> ~[trait_method] {
         do self.parse_unspanned_seq(token::LBRACE, token::RBRACE,
                                     seq_sep_none()) |p| {
             let attrs = p.parse_outer_attributes();
@@ -284,12 +284,42 @@ class parser {
             let ident = p.parse_method_name();
             let tps = p.parse_ty_params();
             let d = p.parse_ty_fn_decl(pur), fhi = p.last_span.hi;
-            self.expect(token::SEMI);
-            {ident: ident, attrs: attrs, decl: {purity: pur with d}, tps: tps,
-             span: mk_sp(flo, fhi)}
+            #debug["parse_trait_methods(): trait method ends in %s",
+                   token_to_str(self.reader, self.token)];
+            alt self.token {
+              token::SEMI {
+                self.bump();
+                required({ident: ident, attrs: attrs,
+                          decl: {purity: pur with d}, tps: tps,
+                          span: mk_sp(flo, fhi)})
+              }
+              token::LBRACE {
+                self.bump();
+                let (inner_attrs, body) =
+                    self.parse_inner_attrs_and_block(true);
+                let attrs = vec::append(attrs, inner_attrs);
+                self.eat(token::RBRACE);
+                provided(@{ident: ident,
+                           attrs: attrs,
+                           tps: tps,
+                           decl: d,
+                           body: body,
+                           id: self.get_id(),
+                           span: mk_sp(flo, fhi),
+                           self_id: self.get_id(),
+                           // Provided traits methods always public for now
+                           vis: public})
+              }
+
+              _ { self.fatal("expected ';' or '}` \
+                              but found `"
+                             + token_to_str(self.reader, self.token) + "`");
+                }
+            }
         }
     }
 
+
     fn parse_mt() -> mt {
         let mutbl = self.parse_mutability();
         let t = self.parse_ty(false);
@@ -2127,7 +2157,7 @@ class parser {
         let ident = self.parse_ident();
         self.parse_region_param();
         let tps = self.parse_ty_params();
-        let meths = self.parse_ty_methods();
+        let meths = self.parse_trait_methods();
         (ident, item_trait(tps, meths), none)
     }
 
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index d43ed8043ee..c802e40dd05 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -5,6 +5,7 @@ import pp::{break_offset, word, printer,
             space, zerobreak, hardbreak, breaks, consistent,
             inconsistent, eof};
 import diagnostic;
+import ast::{required, provided};
 import ast_util::operator_prec;
 import dvec::{dvec, extensions};
 import parse::classify::*;
@@ -593,7 +594,7 @@ fn print_item(s: ps, &&item: @ast::item) {
         print_type_params(s, tps);
         word(s.s, " ");
         bopen(s);
-        for methods.each |meth| { print_ty_method(s, meth); }
+        for methods.each |meth| { print_trait_method(s, meth); }
         bclose(s, item.span);
       }
       ast::item_mac({node: ast::mac_invoc_tt(pth, tts), _}) {
@@ -647,6 +648,13 @@ fn print_ty_method(s: ps, m: ast::ty_method) {
     word(s.s, ";");
 }
 
+fn print_trait_method(s: ps, m: ast::trait_method) {
+    alt m {
+      required(ty_m) { print_ty_method(s, ty_m) }
+      provided(m)    { print_method(s, m) }
+    }
+}
+
 fn print_method(s: ps, meth: @ast::method) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, meth.span.lo);
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 5dc42fd4823..be9f76650da 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -62,6 +62,7 @@ type visitor<E> =
       visit_constr: fn@(@path, span, node_id, E, vt<E>),
       visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt<E>),
       visit_ty_method: fn@(ty_method, E, vt<E>),
+      visit_trait_method: fn@(trait_method, E, vt<E>),
       visit_class_item: fn@(@class_member, E, vt<E>)};
 
 fn default_visitor<E>() -> visitor<E> {
@@ -81,6 +82,7 @@ fn default_visitor<E>() -> visitor<E> {
           visit_constr: |a,b,c,d,e|visit_constr::<E>(a, b, c, d, e),
           visit_fn: |a,b,c,d,e,f,g|visit_fn::<E>(a, b, c, d, e, f, g),
           visit_ty_method: |a,b,c|visit_ty_method::<E>(a, b, c),
+          visit_trait_method: |a,b,c|visit_trait_method::<E>(a, b, c),
           visit_class_item: |a,b,c|visit_class_item::<E>(a, b, c)};
 }
 
@@ -160,7 +162,7 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
       item_trait(tps, methods) {
         v.visit_ty_params(tps, e, v);
         for methods.each |m| {
-            v.visit_ty_method(m, e, v);
+            v.visit_trait_method(m, e, v);
         }
       }
       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>) {
     v.visit_ty(m.decl.output, e, v);
 }
 
+fn visit_trait_method<E>(m: trait_method, e: E, v: vt<E>) {
+    alt m {
+      required(ty_m) {
+        v.visit_ty_method(ty_m, e, v)
+      }
+      provided(m) {
+        visit_method_helper(m, e, v)
+      }
+    }
+}
+
 fn visit_block<E>(b: ast::blk, e: E, v: vt<E>) {
     for b.node.view_items.each |vi| { v.visit_view_item(vi, e, v); }
     for b.node.stmts.each |s| { v.visit_stmt(s, e, v); }
@@ -465,6 +478,7 @@ type simple_visitor =
       visit_constr: fn@(@path, span, node_id),
       visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id),
       visit_ty_method: fn@(ty_method),
+      visit_trait_method: fn@(trait_method),
       visit_class_item: fn@(@class_member)};
 
 fn simple_ignore_ty(_t: @ty) {}
@@ -487,6 +501,7 @@ fn default_simple_visitor() -> simple_visitor {
           visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span,
                         _id: node_id) { },
           visit_ty_method: fn@(_m: ty_method) { },
+          visit_trait_method: fn@(_m: trait_method) { },
           visit_class_item: fn@(_c: @class_member) {}
          };
 }
@@ -546,6 +561,11 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
         f(ty);
         visit_ty_method(ty, e, v);
     }
+    fn v_trait_method(f: fn@(trait_method), m: trait_method, &&e: (),
+                      v: vt<()>) {
+        f(m);
+        visit_trait_method(m, e, v);
+    }
     fn v_ty_params(f: fn@(~[ty_param]),
                    ps: ~[ty_param],
                    &&e: (), v: vt<()>) {
@@ -596,6 +616,8 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
                     v_fn(v.visit_fn, a, b, c, d, e, f, g),
                 visit_ty_method: |a,b,c|
                     v_ty_method(v.visit_ty_method, a, b, c),
+                visit_trait_method: |a,b,c|
+                    v_trait_method(v.visit_trait_method, a, b, c),
                 visit_class_item: |a,b,c|
                     v_class_item(v.visit_class_item, a, b, c)
                });
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index 7539d2be00b..74fd9e1c17e 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -744,12 +744,21 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_name(ebml_w, item.ident);
         let mut i = 0u;
         for vec::each(*ty::trait_methods(tcx, local_def(item.id))) |mty| {
-            ebml_w.start_tag(tag_item_trait_method);
-            encode_name(ebml_w, mty.ident);
-            encode_type_param_bounds(ebml_w, ecx, ms[i].tps);
-            encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
-            encode_family(ebml_w, purity_fn_family(mty.purity));
-            ebml_w.end_tag();
+            alt ms[i] {
+              required(ty_m) {
+                ebml_w.start_tag(tag_item_trait_method);
+                encode_name(ebml_w, mty.ident);
+                encode_type_param_bounds(ebml_w, ecx, ty_m.tps);
+                encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
+                encode_family(ebml_w, purity_fn_family(mty.purity));
+                ebml_w.end_tag();
+              }
+              provided(m) {
+                encode_info_for_method(ecx, ebml_w, path,
+                                       should_inline(m.attrs), item.id,
+                                       m, m.tps);
+              }
+            }
             i += 1u;
         }
         encode_path(ebml_w, path, ast_map::path_name(item.ident));
diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs
index f2eea665522..8efdfac95ea 100644
--- a/src/rustc/middle/resolve.rs
+++ b/src/rustc/middle/resolve.rs
@@ -1,6 +1,7 @@
 import syntax::{ast, ast_util, codemap, ast_map};
 import syntax::ast::*;
 import ast::{ident, fn_ident, def, def_id, node_id};
+import ast::{required, provided};
 import syntax::ast_util::{local_def, def_id_of_def, new_def_hash,
                           class_item_ident, path_to_ident};
 import pat_util::*;
@@ -566,12 +567,8 @@ fn visit_item_with_scope(e: @env, i: @ast::item,
       }
       ast::item_trait(tps, methods) {
         v.visit_ty_params(tps, sc, v);
-        let isc = @cons(scope_method(i.id, tps), sc);
         for methods.each |m| {
-            v.visit_ty_params(m.tps, isc, v);
-            let msc = @cons(scope_method(i.id, vec::append(tps, m.tps)), sc);
-            for m.decl.inputs.each |a| { v.visit_ty(a.ty, msc, v); }
-            v.visit_ty(m.decl.output, msc, v);
+            visit_trait_method(m, i, tps, sc, v);
         }
       }
       ast::item_class(tps, traits, members, ctor, m_dtor) {
@@ -618,6 +615,27 @@ fn visit_item_with_scope(e: @env, i: @ast::item,
     e.resolve_unexported = old_resolve_unexported;
 }
 
+fn visit_trait_method(m: trait_method, i: @ast::item,
+                      tps: ~[ast::ty_param], sc: scopes,
+                      v: vt<scopes>) {
+    alt m {
+      required(ty_m) {
+        let isc = @cons(scope_method(i.id, tps), sc);
+        v.visit_ty_params(ty_m.tps, isc, v);
+        let msc = @cons(scope_method(i.id, vec::append(tps, ty_m.tps)), sc);
+        for ty_m.decl.inputs.each |a| { v.visit_ty(a.ty, msc, v); }
+        v.visit_ty(ty_m.decl.output, msc, v);
+      }
+      provided(m) {
+         v.visit_ty_params(m.tps, sc, v);
+        let msc = @cons(scope_method(m.self_id, vec::append(tps, m.tps)),
+                        sc);
+        v.visit_fn(visit::fk_method(m.ident, ~[], m),
+                   m.decl, m.body, m.span, m.id, msc, v);
+      }
+    }
+}
+
 fn visit_foreign_item_with_scope(ni: @ast::foreign_item, &&sc: scopes,
                                 v: vt<scopes>) {
     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<()>) {
                       "type parameter");
       }
       ast::item_trait(_, methods) {
-        ensure_unique(*e, i.span, methods, |m| m.ident,
+        ensure_unique(*e, i.span, methods, |m| {
+            alt m {
+              required(ty_m) {
+                ty_m.ident
+              }
+              provided(m) {
+                m.ident
+              }
+            }
+        },
                       "method");
       }
       ast::item_impl(_, _, _, methods) {
diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs
index ae1b4eebef4..138f021982a 100644
--- a/src/rustc/middle/resolve3.rs
+++ b/src/rustc/middle/resolve3.rs
@@ -26,6 +26,7 @@ import syntax::ast::{ty_param, ty_path, ty_str, ty_u, ty_u16, ty_u32, ty_u64};
 import syntax::ast::{ty_u8, ty_uint, variant, view_item, view_item_export};
 import syntax::ast::{view_item_import, view_item_use, view_path_glob};
 import syntax::ast::{view_path_list, view_path_simple};
+import syntax::ast::{required, provided};
 import syntax::ast_util::{def_id_of_def, dummy_sp, local_def, new_def_hash};
 import syntax::ast_util::{walk_pat};
 import syntax::attr::{attr_metas, contains_name};
@@ -2928,21 +2929,33 @@ class Resolver {
                         //
                         // XXX: Do we need a node ID here?
 
-                        do self.with_type_parameter_rib
-                                (HasTypeParameters(&method.tps,
+                        alt method {
+                          required(ty_m) {
+                            do self.with_type_parameter_rib
+                                (HasTypeParameters(&ty_m.tps,
                                                    item.id,
                                                    type_parameters.len(),
                                                    NormalRibKind))
-                                || {
+                            || {
 
-                            // Resolve the method-specific type parameters.
-                            self.resolve_type_parameters(method.tps, visitor);
+                                // Resolve the method-specific type
+                                // parameters.
+                                self.resolve_type_parameters(ty_m.tps,
+                                                             visitor);
 
-                            for method.decl.inputs.each |argument| {
-                                self.resolve_type(argument.ty, visitor);
-                            }
+                                for ty_m.decl.inputs.each |argument| {
+                                    self.resolve_type(argument.ty, visitor);
+                                }
 
-                            self.resolve_type(method.decl.output, visitor);
+                                self.resolve_type(ty_m.decl.output, visitor);
+                            }
+                          }
+                          provided(m) {
+                              self.resolve_method(NormalRibKind,
+                                                  m,
+                                                  type_parameters.len(),
+                                                  visitor)
+                          }
                         }
                     }
                 }
@@ -3242,19 +3255,10 @@ class Resolver {
             for class_members.each |class_member| {
                 alt class_member.node {
                     class_method(method) {
-                        let borrowed_method_type_parameters = &method.tps;
-                        let type_parameters =
-                            HasTypeParameters(borrowed_method_type_parameters,
-                                              method.id,
-                                              outer_type_parameter_count,
-                                              NormalRibKind);
-                        self.resolve_function(NormalRibKind,
-                                              some(@method.decl),
-                                              type_parameters,
-                                              method.body,
-                                              HasSelfBinding(method.self_id),
-                                              NoCaptureClause,
-                                              visitor);
+                      self.resolve_method(NormalRibKind,
+                                          method,
+                                          outer_type_parameter_count,
+                                          visitor);
                     }
                     instance_var(_, field_type, _, _, _) {
                         self.resolve_type(field_type, visitor);
@@ -3291,6 +3295,27 @@ class Resolver {
         }
     }
 
+    // Does this really need to take a RibKind or is it always going
+    // to be NormalRibKind?
+    fn resolve_method(rib_kind: RibKind,
+                      method: @method,
+                      outer_type_parameter_count: uint,
+                      visitor: ResolveVisitor) {
+        let borrowed_method_type_parameters = &method.tps;
+        let type_parameters =
+            HasTypeParameters(borrowed_method_type_parameters,
+                              method.id,
+                              outer_type_parameter_count,
+                              rib_kind);
+        self.resolve_function(rib_kind,
+                              some(@method.decl),
+                              type_parameters,
+                              method.body,
+                              HasSelfBinding(method.self_id),
+                              NoCaptureClause,
+                              visitor);
+    }
+
     fn resolve_implementation(id: node_id,
                               span: span,
                               type_parameters: ~[ty_param],
diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs
index 3b10bb3bae3..d8db0533156 100644
--- a/src/rustc/middle/typeck.rs
+++ b/src/rustc/middle/typeck.rs
@@ -41,6 +41,7 @@ independently:
 import result::{result, extensions};
 import syntax::{ast, ast_util, ast_map};
 import ast::spanned;
+import ast::{required, provided};
 import syntax::ast_map::node_id_to_str;
 import syntax::ast_util::{local_def, respan, split_class_items};
 import syntax::visit;
diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs
index fa5ffc61bae..30c5c04dc04 100644
--- a/src/rustc/middle/typeck/collect.rs
+++ b/src/rustc/middle/typeck/collect.rs
@@ -147,8 +147,15 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id) {
     let rp = tcx.region_paramd_items.contains_key(id);
     alt check tcx.items.get(id) {
       ast_map::node_item(@{node: ast::item_trait(_, ms), _}, _) {
-        store_methods::<ast::ty_method>(ccx, id, ms, |m| {
-            ty_of_ty_method(ccx, m, rp)
+        store_methods::<ast::trait_method>(ccx, id, ms, |m| {
+            alt m {
+              required(ty_m) {
+                ty_of_ty_method(ccx, ty_m, rp)
+              }
+              provided(m) {
+                ty_of_method(ccx, m, rp)
+              }
+            }
         });
       }
       ast_map::node_item(@{node: ast::item_class(_,_,its,_,_), _}, _) {
diff --git a/src/rustdoc/attr_pass.rs b/src/rustdoc/attr_pass.rs
index cf2077bfb5e..0d950b33fe7 100644
--- a/src/rustdoc/attr_pass.rs
+++ b/src/rustdoc/attr_pass.rs
@@ -207,7 +207,14 @@ fn merge_method_attrs(
             node: ast::item_trait(_, methods), _
           }, _) {
             par::seqmap(methods, |method| {
-                (*method.ident, attr_parser::parse_desc(method.attrs))
+                alt method {
+                  ast::required(ty_m) {
+                    (*ty_m.ident, attr_parser::parse_desc(ty_m.attrs))
+                  }
+                  ast::provided(m) {
+                    (*m.ident, attr_parser::parse_desc(m.attrs))
+                  }
+                }
             })
           }
           ast_map::node_item(@{
diff --git a/src/rustdoc/doc.rs b/src/rustdoc/doc.rs
index facd84c7a31..9db3f9a607e 100644
--- a/src/rustdoc/doc.rs
+++ b/src/rustdoc/doc.rs
@@ -11,6 +11,11 @@ enum page {
     itempage(itemtag)
 }
 
+enum implementation {
+    required,
+    provided,
+}
+
 /**
  * Most rustdocs can be parsed into 'sections' according to their markdown
  * headers
@@ -91,7 +96,8 @@ type methoddoc = {
     brief: option<str>,
     desc: option<str>,
     sections: ~[section],
-    sig: option<str>
+    sig: option<str>,
+    implementation: implementation,
 };
 
 type impldoc = {
diff --git a/src/rustdoc/extract.rs b/src/rustdoc/extract.rs
index 955c0976c23..72b7150a72e 100644
--- a/src/rustdoc/extract.rs
+++ b/src/rustdoc/extract.rs
@@ -185,17 +185,32 @@ fn should_extract_enum_variants() {
 
 fn traitdoc_from_trait(
     itemdoc: doc::itemdoc,
-    methods: ~[ast::ty_method]
+    methods: ~[ast::trait_method]
 ) -> doc::traitdoc {
     {
         item: itemdoc,
         methods: do par::seqmap(methods) |method| {
-            {
-                name: *method.ident,
-                brief: none,
-                desc: none,
-                sections: ~[],
-                sig: none
+            alt method {
+              ast::required(ty_m) {
+                {
+                    name: *ty_m.ident,
+                    brief: none,
+                    desc: none,
+                    sections: ~[],
+                    sig: none,
+                    implementation: doc::required,
+                }
+              }
+              ast::provided(m) {
+                {
+                    name: *m.ident,
+                    brief: none,
+                    desc: none,
+                    sections: ~[],
+                    sig: none,
+                    implementation: doc::provided,
+                }
+              }
             }
         }
     }
@@ -227,7 +242,8 @@ fn impldoc_from_impl(
                 brief: none,
                 desc: none,
                 sections: ~[],
-                sig: none
+                sig: none,
+                implementation: doc::provided,
             }
         }
     }
diff --git a/src/rustdoc/tystr_pass.rs b/src/rustdoc/tystr_pass.rs
index ba5abf9f66d..011420bdcf4 100644
--- a/src/rustdoc/tystr_pass.rs
+++ b/src/rustdoc/tystr_pass.rs
@@ -171,14 +171,28 @@ fn get_method_sig(
             node: ast::item_trait(_, methods), _
           }, _) {
             alt check vec::find(methods, |method| {
-                *method.ident == method_name
+                alt method {
+                  ast::required(ty_m) { *ty_m.ident == method_name }
+                  ast::provided(m) { *m.ident == method_name }
+                }
             }) {
                 some(method) {
-                    some(pprust::fun_to_str(
-                        method.decl,
-                        method.ident,
-                        method.tps
-                    ))
+                  alt method {
+                    ast::required(ty_m) {
+                      some(pprust::fun_to_str(
+                          ty_m.decl,
+                          ty_m.ident,
+                          ty_m.tps
+                      ))
+                    }
+                    ast::provided(m) {
+                      some(pprust::fun_to_str(
+                          m.decl,
+                          m.ident,
+                          m.tps
+                      ))
+                    }
+                  }
                 }
             }
           }