about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/typeck/coherence.rs32
-rw-r--r--src/test/auxiliary/trait_impl_conflict.rs15
-rw-r--r--src/test/compile-fail/conflicting-implementations-aux.rs24
3 files changed, 66 insertions, 5 deletions
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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<A> 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() {
+}