diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 7de2de708cc..674bb8d6f85 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -124,46 +124,8 @@ fn lookup_vtable_covariant(vcx: &VtableContext, vcx.infcx.ty_to_str(ty), vcx.infcx.ty_to_str(trait_ty)); - let worklist = dvec::DVec(); - worklist.push(trait_ty); - while worklist.len() > 0 { - let trait_ty = worklist.pop(); - let result = lookup_vtable_invariant(vcx, location_info, ty, trait_ty, - allow_unsafe, is_early); - if result.is_some() { - return result; - } - - // Add subtraits to the worklist, if applicable. - match ty::get(trait_ty).sty { - ty::ty_trait(trait_id, _, _) => { - let table = vcx.ccx.coherence_info.supertrait_to_subtraits; - match table.find(trait_id) { - None => {} - Some(subtraits) => { - for subtraits.each |subtrait_id| { - // XXX: This is wrong; subtraits should themselves - // have substs. - let substs = - { self_r: None, self_ty: None, tps: ~[] }; - let trait_ty = ty::mk_trait(vcx.tcx(), - *subtrait_id, - substs, - ty::vstore_box); - worklist.push(trait_ty); - } - } - } - } - _ => { - vcx.tcx().sess.impossible_case(location_info.span, - "lookup_vtable_covariant: \ - non-trait in worklist"); - } - } - } - - return None; + lookup_vtable_invariant(vcx, location_info, ty, trait_ty, + allow_unsafe, is_early) } // Look up the vtable to use when treating an item of type `t` as if it has diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 97968e11ffa..d441f11959d 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -144,9 +144,6 @@ struct CoherenceInfo { // the associated trait must be imported at the call site. extension_methods: HashMap>, - // A mapping from a supertrait to its subtraits. - supertrait_to_subtraits: HashMap>, - // A mapping from an implementation ID to the method info and trait method // ID of the provided (a.k.a. default) methods in the traits that that // implementation implements. @@ -157,7 +154,6 @@ fn CoherenceInfo() -> CoherenceInfo { CoherenceInfo { inherent_methods: HashMap(), extension_methods: HashMap(), - supertrait_to_subtraits: HashMap(), provided_methods: HashMap(), } } @@ -204,9 +200,6 @@ impl CoherenceChecker { item_class(struct_def, _) => { self.check_implementation(item, struct_def.traits); } - item_trait(_, supertraits, _) => { - self.register_inherited_trait(item, supertraits); - } _ => { // Nothing to do. } @@ -215,12 +208,8 @@ impl CoherenceChecker { .. *default_simple_visitor() })); - // Check trait coherence. - for self.crate_context.coherence_info.extension_methods.each - |def_id, items| { - - self.check_implementation_coherence(def_id, items); - } + // Check that there are no overlapping trait instances + self.check_implementation_coherence(); // Check whether traits with base types are in privileged scopes. self.check_privileged_scopes(crate); @@ -377,27 +366,6 @@ impl CoherenceChecker { } } - fn register_inherited_trait(item: @item, supertraits: ~[@trait_ref]) { - // XXX: This is wrong. We need to support substitutions; e.g. - // trait Foo : Bar. - let supertrait_to_subtraits = - self.crate_context.coherence_info.supertrait_to_subtraits; - let subtrait_id = local_def(item.id); - for supertraits.each |supertrait| { - let supertrait_id = self.trait_ref_to_trait_def_id(*supertrait); - match supertrait_to_subtraits.find(supertrait_id) { - None => { - let new_vec = @dvec::DVec(); - new_vec.push(subtrait_id); - supertrait_to_subtraits.insert(supertrait_id, new_vec); - } - Some(existing_vec) => { - existing_vec.push(subtrait_id); - } - } - } - } - fn add_inherent_method(base_def_id: def_id, implementation: @Impl) { let implementation_list; match self.crate_context.coherence_info.inherent_methods @@ -432,32 +400,60 @@ impl CoherenceChecker { implementation_list.push(implementation); } - fn check_implementation_coherence(_trait_def_id: def_id, - implementations: @DVec<@Impl>) { + fn check_implementation_coherence() { + let coherence_info = &self.crate_context.coherence_info; + let extension_methods = &coherence_info.extension_methods; + + for extension_methods.each_key |trait_id| { + self.check_implementation_coherence_of(trait_id); + } + } + + fn check_implementation_coherence_of(trait_def_id: def_id) { // Unify pairs of polytypes. - for range(0, implementations.len()) |i| { - let implementation_a = implementations.get_elt(i); + do self.iter_impls_of_trait(trait_def_id) |a| { + let implementation_a = a; let polytype_a = self.get_self_type_for_implementation(implementation_a); - for range(i + 1, implementations.len()) |j| { - let implementation_b = implementations.get_elt(j); - let polytype_b = - self.get_self_type_for_implementation(implementation_b); + do self.iter_impls_of_trait(trait_def_id) |b| { + let implementation_b = b; - if self.polytypes_unify(polytype_a, polytype_b) { - let session = self.crate_context.tcx.sess; - session.span_err(self.span_of_impl(implementation_b), - ~"conflicting implementations for a \ - trait"); - session.span_note(self.span_of_impl(implementation_a), - ~"note conflicting implementation \ - here"); + // An impl is coherent with itself + if a.did != b.did { + let polytype_b = self.get_self_type_for_implementation( + implementation_b); + + if self.polytypes_unify(polytype_a, polytype_b) { + let session = self.crate_context.tcx.sess; + session.span_err(self.span_of_impl(implementation_b), + ~"conflicting implementations for a \ + trait"); + session.span_note(self.span_of_impl(implementation_a), + ~"note conflicting implementation \ + here"); + } } } } } + fn iter_impls_of_trait(trait_def_id: def_id, + f: &fn(@Impl)) { + + let coherence_info = &self.crate_context.coherence_info; + let extension_methods = &coherence_info.extension_methods; + + match extension_methods.find(trait_def_id) { + Some(impls) => { + for uint::range(0, impls.len()) |i| { + f(impls[i]); + } + } + None => { /* no impls? */ } + } + } + fn each_provided_trait_method( trait_did: ast::def_id, f: &fn(x: &ty::method) -> bool) {