about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libsyntax/ast.rs6
-rw-r--r--src/libsyntax/ext/pipes/pipec.rs1
-rw-r--r--src/libsyntax/parse/parser.rs29
-rw-r--r--src/libsyntax/print/pprust.rs10
-rw-r--r--src/libsyntax/visit.rs6
-rw-r--r--src/rustc/metadata/encoder.rs20
-rw-r--r--src/rustc/middle/resolve3.rs20
-rw-r--r--src/rustc/middle/ty.rs9
-rw-r--r--src/rustc/middle/typeck/check/method.rs14
-rw-r--r--src/rustc/middle/typeck/coherence.rs36
-rw-r--r--src/rustdoc/doc.rs2
-rw-r--r--src/rustdoc/extract.rs2
-rw-r--r--src/rustdoc/markdown_pass.rs16
-rw-r--r--src/rustdoc/tystr_pass.rs18
14 files changed, 126 insertions, 63 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 65ff9245fd1..79523acb99b 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -635,8 +635,10 @@ enum item_ {
                option<class_dtor>
                ),
     item_trait(~[ty_param], ~[trait_method]),
-    item_impl(~[ty_param], option<@trait_ref> /* trait */,
-              @ty /* self */, ~[@method]),
+    item_impl(~[ty_param],
+              ~[@trait_ref], /* traits this impl implements */
+              @ty, /* self */
+              ~[@method]),
     item_mac(mac),
 }
 
diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs
index c6b1a2d6932..df5df748a74 100644
--- a/src/libsyntax/ext/pipes/pipec.rs
+++ b/src/libsyntax/ext/pipes/pipec.rs
@@ -21,6 +21,7 @@ import ast_builder::append_types;
 import ast_builder::ast_builder;
 import ast_builder::methods;
 import ast_builder::path;
+import ast_builder::path_concat;
 
 trait gen_send {
     fn gen_send(cx: ext_ctxt) -> @ast::item;
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 8336d6b39ab..6bcf22c8220 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2085,13 +2085,22 @@ class parser {
                 (some(id), self.parse_ty_params())
             }
         };
-        let ifce = if self.eat_keyword(~"of") {
-            let path = self.parse_path_with_tps(false);
-            if option::is_none(ident) {
-                ident = some(vec::last(path.idents));
+        let traits;
+        if self.eat_keyword(~"of") {
+            let for_atom = interner::intern(*self.reader.interner(), @~"for");
+            traits = self.parse_trait_ref_list(token::IDENT(for_atom, false));
+            if traits.len() >= 1 && option::is_none(ident) {
+                ident = some(vec::last(traits[0].path.idents));
             }
-            some(@{path: path, ref_id: self.get_id(), impl_id: self.get_id()})
-        } else { none };
+            if traits.len() == 0 {
+                self.fatal(~"BUG: 'of' but no trait");
+            }
+            if traits.len() > 1 {
+                self.fatal(~"BUG: multiple traits");
+            }
+        } else {
+            traits = ~[];
+        };
         let ident = alt ident {
           some(name) { name }
           none { self.expect_keyword(~"of"); fail; }
@@ -2103,7 +2112,7 @@ class parser {
         while !self.eat(token::RBRACE) {
             vec::push(meths, self.parse_method(public));
         }
-        (ident, item_impl(tps, ifce, ty, meths), none)
+        (ident, item_impl(tps, traits, ty, meths), none)
     }
 
     // Instantiates ident <i> with references to <typarams> as arguments.
@@ -2127,9 +2136,9 @@ class parser {
           ref_id: self.get_id(), impl_id: self.get_id()}
     }
 
-    fn parse_trait_ref_list() -> ~[@trait_ref] {
+    fn parse_trait_ref_list(ket: token::token) -> ~[@trait_ref] {
         self.parse_seq_to_before_end(
-            token::LBRACE, seq_sep_trailing_disallowed(token::COMMA),
+            ket, seq_sep_trailing_disallowed(token::COMMA),
             |p| p.parse_trait_ref())
     }
 
@@ -2139,7 +2148,7 @@ class parser {
         let ty_params = self.parse_ty_params();
         let class_path = self.ident_to_path_tys(class_name, ty_params);
         let traits : ~[@trait_ref] = if self.eat(token::COLON)
-            { self.parse_trait_ref_list() }
+            { self.parse_trait_ref_list(token::LBRACE) }
         else { ~[] };
         self.expect(token::LBRACE);
         let mut ms: ~[@class_member] = ~[];
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 2d087d8d9df..b1730bfc587 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -558,16 +558,18 @@ fn print_item(s: ps, &&item: @ast::item) {
           }
           bclose(s, item.span);
        }
-      ast::item_impl(tps, ifce, ty, methods) {
+      ast::item_impl(tps, traits, ty, methods) {
         head(s, ~"impl");
         word(s.s, *item.ident);
         print_type_params(s, tps);
         space(s.s);
-        option::iter(ifce, |p| {
+        if vec::len(traits) != 0u {
             word_nbsp(s, ~"of");
-            print_path(s, p.path, false);
+            do commasep(s, inconsistent, traits) |s, p| {
+                print_path(s, p.path, false);
+            }
             space(s.s);
-            });
+        }
         word_nbsp(s, ~"for");
         print_type(s, ty);
         space(s.s);
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index ead8e981d7a..14fe18edd09 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -135,9 +135,11 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
             for vr.node.args.each |va| { v.visit_ty(va.ty, e, v); }
         }
       }
-      item_impl(tps, ifce, ty, methods) {
+      item_impl(tps, traits, ty, methods) {
         v.visit_ty_params(tps, e, v);
-        option::iter(ifce, |p| visit_path(p.path, e, v));
+        for traits.each |p| {
+            visit_path(p.path, e, v);
+        }
         v.visit_ty(ty, e, v);
         for methods.each |m| {
             visit_method_helper(m, e, v)
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index 4df1e0aa513..e11008f4d6f 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -410,14 +410,7 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
         ref, we need to map it to its parent class */
             ebml_w.wr_str(def_to_str(local_def(it.id)));
           }
-          some(ast_map::node_item(@{node: item_impl(_,
-                                               some(ifce),_,_),_},_)) {
-            ebml_w.wr_str(def_to_str(did));
-          }
-          some(_) {
-            ebml_w.wr_str(def_to_str(did));
-          }
-          none {
+          _ {
             // Must be a re-export, then!
             // ...or an iface ref
             ebml_w.wr_str(def_to_str(did));
@@ -715,7 +708,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_index(ebml_w, bkts, write_int);
         ebml_w.end_tag();
       }
-      item_impl(tps, ifce, _, methods) {
+      item_impl(tps, traits, _, methods) {
         add_to_index();
         ebml_w.start_tag(tag_items_data_item);
         encode_def_id(ebml_w, local_def(item.id));
@@ -729,9 +722,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
             ebml_w.writer.write(str::bytes(def_to_str(local_def(m.id))));
             ebml_w.end_tag();
         }
-        do option::iter(ifce) |t| {
-           encode_trait_ref(ebml_w, ecx, t)
-        };
+        if traits.len() > 1 {
+            fail ~"multiple traits!!";
+        }
+        for traits.each |associated_trait| {
+           encode_trait_ref(ebml_w, ecx, associated_trait)
+        }
         encode_path(ebml_w, path, ast_map::path_name(item.ident));
         ebml_w.end_tag();
 
diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs
index 04a7448f798..55bc99fa688 100644
--- a/src/rustc/middle/resolve3.rs
+++ b/src/rustc/middle/resolve3.rs
@@ -2966,16 +2966,20 @@ class Resolver {
                 }
             }
 
-            item_impl(type_parameters, interface_reference, self_type,
+            item_impl(type_parameters, implemented_traits, self_type,
                       methods) {
 
-                self.resolve_implementation(item.id,
-                                            item.span,
-                                            type_parameters,
-                                            interface_reference,
-                                            self_type,
-                                            methods,
-                                            visitor);
+                // XXX: Should take an array of traits.
+                let trait_reference;
+                if implemented_traits.len() == 0 {
+                    trait_reference = none;
+                } else {
+                    trait_reference = some(implemented_traits[0]);
+                }
+
+                self.resolve_implementation(item.id, item.span,
+                                            type_parameters, trait_reference,
+                                            self_type, methods, visitor);
             }
 
             item_trait(type_parameters, methods) {
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index 08ef9fb6bff..b750870ff86 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -2474,13 +2474,16 @@ fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
     result
 }
 
+// XXX: Needs to return an array of traits.
 fn impl_trait(cx: ctxt, id: ast::def_id) -> option<t> {
     if id.crate == ast::local_crate {
         #debug("(impl_trait) searching for trait impl %?", id);
         alt cx.items.find(id.node) {
-           some(ast_map::node_item(@{node: ast::item_impl(
-              _, some(@{ref_id: id, _}), _, _), _}, _)) {
-              some(node_id_to_type(cx, id))
+           some(ast_map::node_item(@{
+                    node: ast::item_impl(_, traits, _, _),
+                    _},
+                _)) if traits.len() >= 1 {
+              some(node_id_to_type(cx, traits[0].ref_id))
            }
            some(ast_map::node_item(@{node: ast::item_class(*),
                            _},_)) {
diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs
index c2135249c9c..7f269944059 100644
--- a/src/rustc/middle/typeck/check/method.rs
+++ b/src/rustc/middle/typeck/check/method.rs
@@ -454,7 +454,7 @@ class lookup {
                 for (*trait_ids).each |trait_id| {
                     #debug("(adding inherent and extension candidates) \
                             trying trait: %s",
-                           node_id_to_str(self.tcx().items, trait_id.node));
+                           self.def_id_to_str(trait_id));
 
                     let coherence_info = self.fcx.ccx.coherence_info;
                     alt coherence_info.extension_methods.find(trait_id) {
@@ -463,6 +463,10 @@ class lookup {
                         }
                         some(extension_methods) {
                             for extension_methods.each |implementation| {
+                                #debug("(adding inherent and extension \
+                                         candidates) adding impl %s",
+                                       self.def_id_to_str
+                                        (implementation.did));
                                 self.add_candidates_from_impl
                                     (implementation, use_assignability);
                             }
@@ -473,6 +477,14 @@ class lookup {
         }
     }
 
+    fn def_id_to_str(def_id: ast::def_id) -> ~str {
+        if def_id.crate == ast::local_crate {
+            node_id_to_str(self.tcx().items, def_id.node)
+        } else {
+            ast_map::path_to_str(csearch::get_item_path(self.tcx(), def_id))
+        }
+    }
+
     fn write_mty_from_candidate(cand: candidate) -> method_map_entry {
         let tcx = self.fcx.ccx.tcx;
 
diff --git a/src/rustc/middle/typeck/coherence.rs b/src/rustc/middle/typeck/coherence.rs
index 19b4450bb62..f0c70cbc3a9 100644
--- a/src/rustc/middle/typeck/coherence.rs
+++ b/src/rustc/middle/typeck/coherence.rs
@@ -154,9 +154,21 @@ class CoherenceChecker {
 
         visit_crate(*crate, (), mk_simple_visitor(@{
             visit_item: |item| {
+                #debug("(checking coherence) item '%s'", *item.ident);
+
                 alt item.node {
-                    item_impl(_, associated_trait, self_type, _) {
-                        self.check_implementation(item, associated_trait);
+                    item_impl(_, associated_traits, self_type, _) {
+                        // XXX: Accept an array of traits.
+                        let optional_associated_trait;
+                        if associated_traits.len() == 0 {
+                            optional_associated_trait = none;
+                        } else {
+                            optional_associated_trait =
+                                some(associated_traits[0]);
+                        }
+
+                        self.check_implementation(item,
+                                                  optional_associated_trait);
                     }
                     _ {
                         // Nothing to do.
@@ -189,6 +201,10 @@ class CoherenceChecker {
         let self_type = self.crate_context.tcx.tcache.get(local_def(item.id));
         alt optional_associated_trait {
             none {
+                #debug("(checking implementation) no associated trait for \
+                        item '%s'",
+                       *item.ident);
+
                 alt get_base_type_def_id(self.inference_context,
                                          item.span,
                                          self_type.ty) {
@@ -207,6 +223,12 @@ class CoherenceChecker {
             some(associated_trait) {
                 let def = self.crate_context.tcx.def_map.get
                     (associated_trait.ref_id);
+                #debug("(checking implementation) adding impl for trait \
+                        '%s', item '%s'",
+                       ast_map::node_id_to_str(self.crate_context.tcx.items,
+                                               associated_trait.ref_id),
+                       *item.ident);
+
                 let implementation = self.create_impl_from_item(item);
                 self.add_trait_method(def_id_of_def(def), implementation);
             }
@@ -362,7 +384,15 @@ class CoherenceChecker {
                             self.privileged_types.remove(privileged_type);
                         }
                     }
-                    item_impl(_, optional_trait_ref, _, _) {
+                    item_impl(_, associated_traits, _, _) {
+                        // XXX: Accept an array of traits.
+                        let optional_trait_ref;
+                        if associated_traits.len() == 0 {
+                            optional_trait_ref = none;
+                        } else {
+                            optional_trait_ref = some(associated_traits[0]);
+                        }
+
                         alt self.base_type_def_ids.find(local_def(item.id)) {
                             none {
                                 // Nothing to do.
diff --git a/src/rustdoc/doc.rs b/src/rustdoc/doc.rs
index efbd9c7cd60..e6c780e6e08 100644
--- a/src/rustdoc/doc.rs
+++ b/src/rustdoc/doc.rs
@@ -110,7 +110,7 @@ type methoddoc = {
 
 type impldoc = {
     item: itemdoc,
-    trait_ty: option<~str>,
+    trait_types: ~[~str],
     self_ty: option<~str>,
     methods: ~[methoddoc]
 };
diff --git a/src/rustdoc/extract.rs b/src/rustdoc/extract.rs
index 343c018a312..bdcfb8cc590 100644
--- a/src/rustdoc/extract.rs
+++ b/src/rustdoc/extract.rs
@@ -235,7 +235,7 @@ fn impldoc_from_impl(
 ) -> doc::impldoc {
     {
         item: itemdoc,
-        trait_ty: none,
+        trait_types: ~[],
         self_ty: none,
         methods: do vec::map(methods) |method| {
             {
diff --git a/src/rustdoc/markdown_pass.rs b/src/rustdoc/markdown_pass.rs
index f3962f2a30e..b04210f4d31 100644
--- a/src/rustdoc/markdown_pass.rs
+++ b/src/rustdoc/markdown_pass.rs
@@ -224,14 +224,16 @@ fn header_name(doc: doc::itemtag) -> ~str {
       doc::impltag(doc) {
         assert option::is_some(doc.self_ty);
         let self_ty = option::get(doc.self_ty);
-        alt doc.trait_ty {
-          some(trait_ty) {
-            #fmt("%s of %s for %s", doc.name(), trait_ty, self_ty)
-          }
-          none {
-            #fmt("%s for %s", doc.name(), self_ty)
-          }
+        let mut trait_part = ~"";
+        for doc.trait_types.eachi |i, trait_type| {
+            if i == 0 {
+                trait_part += ~" of ";
+            } else {
+                trait_part += ", ";
+            }
+            trait_part += trait_type;
         }
+        #fmt("%s%s for %s", doc.name(), trait_part, self_ty)
       }
       _ {
         doc.name()
diff --git a/src/rustdoc/tystr_pass.rs b/src/rustdoc/tystr_pass.rs
index b22c7e121c7..774106a6fb4 100644
--- a/src/rustdoc/tystr_pass.rs
+++ b/src/rustdoc/tystr_pass.rs
@@ -230,22 +230,22 @@ fn fold_impl(
 
     let srv = fold.ctxt;
 
-    let (trait_ty, self_ty) = do astsrv::exec(srv) |ctxt| {
+    let (trait_types, self_ty) = do astsrv::exec(srv) |ctxt| {
         alt ctxt.ast_map.get(doc.id()) {
           ast_map::node_item(@{
-            node: ast::item_impl(_, trait_ty, self_ty, _), _
+            node: ast::item_impl(_, trait_types, self_ty, _), _
           }, _) {
-            let trait_ty = option::map(trait_ty, |p| {
+            let trait_types = vec::map(trait_types, |p| {
                 pprust::path_to_str(p.path)
             });
-            (trait_ty, some(pprust::ty_to_str(self_ty)))
+            (trait_types, some(pprust::ty_to_str(self_ty)))
           }
           _ { fail ~"expected impl" }
         }
     };
 
     {
-        trait_ty: trait_ty,
+        trait_types: trait_types,
         self_ty: self_ty,
         methods: merge_methods(fold.ctxt, doc.id(), doc.methods)
         with doc
@@ -253,15 +253,15 @@ fn fold_impl(
 }
 
 #[test]
-fn should_add_impl_trait_ty() {
+fn should_add_impl_trait_types() {
     let doc = test::mk_doc(~"impl i of j for int { fn a<T>() { } }");
-    assert doc.cratemod().impls()[0].trait_ty == some(~"j");
+    assert doc.cratemod().impls()[0].trait_types[0] == ~"j";
 }
 
 #[test]
-fn should_not_add_impl_trait_ty_if_none() {
+fn should_not_add_impl_trait_types_if_none() {
     let doc = test::mk_doc(~"impl i for int { fn a() { } }");
-    assert doc.cratemod().impls()[0].trait_ty == none;
+    assert vec::len(doc.cratemod().impls()[0].trait_types) == 0;
 }
 
 #[test]