diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index b1f54e701ac8..140df4c29c0a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1267,7 +1267,7 @@ enum item_ { item_class(@struct_def, ~[ty_param]), item_trait(~[ty_param], ~[@trait_ref], ~[trait_method]), item_impl(~[ty_param], - ~[@trait_ref], /* traits this impl implements */ + Option<@trait_ref>, /* (optional) trait this impl implements */ @ty, /* self */ ~[@method]), item_mac(mac), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a21d9de7567d..2377555dfb3d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2571,11 +2571,11 @@ struct parser { // Parse traits, if necessary. - let traits = if self.token == token::COLON { + let opt_trait = if self.token == token::COLON { self.bump(); - self.parse_trait_ref_list(token::LBRACE) + Some(self.parse_trait_ref()) } else { - ~[] + None }; let mut meths = ~[]; @@ -2584,7 +2584,7 @@ struct parser { let vis = self.parse_visibility(); vec::push(meths, self.parse_method(vis)); } - (ident, item_impl(tps, traits, ty, meths), None) + (ident, item_impl(tps, opt_trait, ty, meths), None) } // Instantiates ident with references to as arguments. diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 451d5be1a500..ae0eac571af7 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -499,7 +499,7 @@ fn print_item(s: ps, &&item: @ast::item) { print_struct(s, struct_def, tps, item.ident, item.span); } - ast::item_impl(tps, traits, ty, methods) => { + ast::item_impl(tps, opt_trait, ty, methods) => { head(s, ~"impl"); if tps.is_not_empty() { print_type_params(s, tps); @@ -507,12 +507,13 @@ fn print_item(s: ps, &&item: @ast::item) { } print_type(s, ty); - if vec::len(traits) != 0u { - word_space(s, ~":"); - do commasep(s, inconsistent, traits) |s, p| { - print_path(s, p.path, false); + match opt_trait { + Some(t) => { + word_space(s, ~":"); + print_path(s, t.path, false); } - } + None => () + }; space(s.s); bopen(s); diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 31f12a4b355a..f45cd38fe832 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -699,7 +699,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item, else { None }, tps); } } - item_impl(tps, traits, _, methods) => { + item_impl(tps, opt_trait, _, methods) => { add_to_index(); ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); @@ -714,10 +714,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item, ebml_w.writer.write(str::to_bytes(def_to_str(local_def(m.id)))); ebml_w.end_tag(); } - if traits.len() > 1 { - fail ~"multiple traits!!"; - } - for traits.each |associated_trait| { + do opt_trait.iter() |associated_trait| { encode_trait_ref(ebml_w, ecx, associated_trait) } encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 1b7f2d60bd7c..32f3348218ab 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -3532,7 +3532,7 @@ struct Resolver { fn resolve_implementation(id: node_id, span: span, type_parameters: ~[ty_param], - trait_references: ~[@trait_ref], + opt_trait_reference: Option<@trait_ref>, self_type: @ty, methods: ~[@method], visitor: ResolveVisitor) { @@ -3549,10 +3549,10 @@ struct Resolver { // Resolve the trait reference, if necessary. let original_trait_refs = self.current_trait_refs; - if trait_references.len() >= 1 { - let mut new_trait_refs = @DVec(); - for trait_references.each |trait_reference| { - match self.resolve_path( + match opt_trait_reference { + Some(trait_reference) => { + let new_trait_refs = @DVec(); + match self.resolve_path( trait_reference.path, TypeNS, true, visitor) { None => { self.session.span_err(span, @@ -3566,11 +3566,11 @@ struct Resolver { (*new_trait_refs).push(def_id_of_def(def)); } } - } - // Record the current set of trait references. self.current_trait_refs = Some(new_trait_refs); } + None => () + } // Resolve the self type. self.resolve_type(self_type, visitor); diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 4c81ccd21420..1d6cd1f45c3a 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -3121,13 +3121,13 @@ fn impl_traits(cx: ctxt, id: ast::def_id) -> ~[t] { debug!("(impl_traits) searching for trait impl %?", id); match cx.items.find(id.node) { Some(ast_map::node_item(@{ - node: ast::item_impl(_, trait_refs, _, _), + node: ast::item_impl(_, opt_trait, _, _), _}, _)) => { - do vec::map(trait_refs) |trait_ref| { - node_id_to_type(cx, trait_ref.ref_id) - } + do option::map_default(opt_trait, ~[]) |trait_ref| { + ~[node_id_to_type(cx, trait_ref.ref_id)] + } } Some(ast_map::node_item(@{node: ast::item_class(sd,_), _},_)) => { diff --git a/src/rustc/middle/typeck/coherence.rs b/src/rustc/middle/typeck/coherence.rs index 768431ce4fbb..434a2b1caf26 100644 --- a/src/rustc/middle/typeck/coherence.rs +++ b/src/rustc/middle/typeck/coherence.rs @@ -231,8 +231,8 @@ struct CoherenceChecker { self.crate_context.tcx.sess.str_of(item.ident)); match item.node { - item_impl(_, associated_traits, _, _) => { - self.check_implementation(item, associated_traits); + item_impl(_, opt_trait, _, _) => { + self.check_implementation(item, opt_trait.to_vec()); } item_class(struct_def, _) => { self.check_implementation(item, struct_def.traits); @@ -432,7 +432,7 @@ struct CoherenceChecker { // Then visit the module items. visit_mod(module_, item.span, item.id, (), visitor); } - item_impl(_, associated_traits, _, _) => { + item_impl(_, opt_trait, _, _) => { match self.base_type_def_ids.find( local_def(item.id)) { @@ -453,7 +453,8 @@ struct CoherenceChecker { // if the traits are defined in the same // crate. - if associated_traits.len() == 0 { + match opt_trait { + None => { // There is no trait to implement, so // this is an error. @@ -470,8 +471,10 @@ struct CoherenceChecker { or new type \ instead"); } + _ => () + } - for associated_traits.each |trait_ref| { + do opt_trait.iter() |trait_ref| { // This is OK if and only if the // trait was defined in this // crate. diff --git a/src/rustdoc/tystr_pass.rs b/src/rustdoc/tystr_pass.rs index 3ea9d0fa81b8..68a3c94316e6 100644 --- a/src/rustdoc/tystr_pass.rs +++ b/src/rustdoc/tystr_pass.rs @@ -243,10 +243,10 @@ fn fold_impl( let (trait_types, self_ty) = do astsrv::exec(srv) |ctxt| { match ctxt.ast_map.get(doc.id()) { ast_map::node_item(@{ - node: ast::item_impl(_, trait_types, self_ty, _), _ + node: ast::item_impl(_, opt_trait_type, self_ty, _), _ }, _) => { - let trait_types = vec::map(trait_types, |p| { - pprust::path_to_str(p.path, extract::interner()) + let trait_types = opt_trait_type.map_default(~[], |p| { + ~[pprust::path_to_str(p.path, extract::interner())] }); (trait_types, Some(pprust::ty_to_str(self_ty, extract::interner()))) diff --git a/src/test/compile-fail/multitrait.rs b/src/test/compile-fail/multitrait.rs new file mode 100644 index 000000000000..6ce063ecf170 --- /dev/null +++ b/src/test/compile-fail/multitrait.rs @@ -0,0 +1,8 @@ +struct S { + y: int; +} + +impl S: Cmp, ToStr { //~ ERROR: expected `{` but found `,` + fn eq(&&other: S) { false } + fn to_str() -> ~str { ~"hi" } +} \ No newline at end of file