diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 5ca879fea4a..06776fc672e 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -15,7 +15,7 @@ // each trait in the system to its implementations. -use metadata::csearch::{each_impl, get_impl_trait}; +use metadata::csearch::{each_impl, get_impl_trait, each_implementation_for_trait}; use metadata::csearch; use middle::ty::get; use middle::ty::{ImplContainer, lookup_item_type, subst}; @@ -434,7 +434,7 @@ impl CoherenceChecker { pub fn check_implementation_coherence_of(&self, trait_def_id: DefId) { // Unify pairs of polytypes. - self.iter_impls_of_trait(trait_def_id, |a| { + self.iter_impls_of_trait_local(trait_def_id, |a| { let implementation_a = a; let polytype_a = self.get_self_type_for_implementation(implementation_a); @@ -452,12 +452,19 @@ impl CoherenceChecker { if self.polytypes_unify(polytype_a.clone(), polytype_b) { let session = self.crate_context.tcx.sess; session.span_err( - self.span_of_impl(implementation_b), + self.span_of_impl(implementation_a), format!("conflicting implementations for trait `{}`", ty::item_path_str(self.crate_context.tcx, trait_def_id))); - session.span_note(self.span_of_impl(implementation_a), - "note conflicting implementation here"); + if implementation_b.did.crate == LOCAL_CRATE { + session.span_note(self.span_of_impl(implementation_b), + "note conflicting implementation here"); + } else { + let crate_store = self.crate_context.tcx.sess.cstore; + let cdata = crate_store.get_crate_data(implementation_b.did.crate); + session.note( + "conflicting implementation in crate `" + cdata.name + "`"); + } } } }) @@ -465,6 +472,21 @@ impl CoherenceChecker { } pub fn iter_impls_of_trait(&self, trait_def_id: DefId, f: |@Impl|) { + self.iter_impls_of_trait_local(trait_def_id, |x| f(x)); + + if trait_def_id.crate == LOCAL_CRATE { + return; + } + + let crate_store = self.crate_context.tcx.sess.cstore; + csearch::each_implementation_for_trait(crate_store, trait_def_id, |impl_def_id| { + let implementation = @csearch::get_impl(self.crate_context.tcx, impl_def_id); + let _ = lookup_item_type(self.crate_context.tcx, implementation.did); + f(implementation); + }); + } + + pub fn iter_impls_of_trait_local(&self, trait_def_id: DefId, f: |@Impl|) { let trait_impls = self.crate_context.tcx.trait_impls.borrow(); match trait_impls.get().find(&trait_def_id) { Some(impls) => { diff --git a/src/test/auxiliary/trait_impl_conflict.rs b/src/test/auxiliary/trait_impl_conflict.rs new file mode 100644 index 00000000000..990bc216049 --- /dev/null +++ b/src/test/auxiliary/trait_impl_conflict.rs @@ -0,0 +1,15 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait Foo { +} + +impl Foo for int { +} diff --git a/src/test/compile-fail/conflicting-implementations-aux.rs b/src/test/compile-fail/conflicting-implementations-aux.rs new file mode 100644 index 00000000000..e39059124a0 --- /dev/null +++ b/src/test/compile-fail/conflicting-implementations-aux.rs @@ -0,0 +1,24 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #3512 - conflicting trait impls in different crates should give a +// 'conflicting implementations' error message. + +// aux-build:trait_impl_conflict.rs +extern mod trait_impl_conflict; +use trait_impl_conflict::Foo; + +impl Foo for A { +//~^ ERROR conflicting implementations for trait `trait_impl_conflict::Foo` +//~^^ ERROR cannot provide an extension implementation where both trait and type are not defined in this crate +} + +fn main() { +}