about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSean Griffin <sean@seantheprogrammer.com>2017-03-17 12:43:15 -0400
committerCorey Farwell <coreyf@rwell.org>2017-04-14 22:04:53 -0400
commitc81c958e984b92222909e2ba5c74a2260a44bdae (patch)
tree6e1532f5663b9c6d4ed4538da5b992d2ca959827
parentddcca79d25fffd6604fba593b1ca642a9dfa5727 (diff)
downloadrust-c81c958e984b92222909e2ba5c74a2260a44bdae.tar.gz
rust-c81c958e984b92222909e2ba5c74a2260a44bdae.zip
Further update with response to feedback
-rw-r--r--src/librustc/traits/select.rs3
-rw-r--r--src/librustc/traits/specialize/mod.rs5
-rw-r--r--src/librustc/traits/specialize/specialization_graph.rs5
-rw-r--r--src/librustc/ty/mod.rs22
-rw-r--r--src/test/compile-fail/auxiliary/trait_impl_conflict.rs1
5 files changed, 19 insertions, 17 deletions
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 67d50210ba3..410eb2b8484 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -1736,7 +1736,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 if other.evaluation == EvaluatedToOk {
                     if let ImplCandidate(victim_def) = victim.candidate {
                         let tcx = self.tcx().global_tcx();
-                        return traits::specializes(tcx, other_def, victim_def);
+                        return traits::specializes(tcx, other_def, victim_def) ||
+                            tcx.impls_are_allowed_to_overlap(other_def, victim_def);
                     }
                 }
 
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 6455de48a29..50a4d982832 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -155,11 +155,6 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return r;
     }
 
-    if tcx.impl_always_allowed_to_overlap(impl1_def_id)
-        && tcx.impl_always_allowed_to_overlap(impl2_def_id) {
-        return true;
-    }
-
     // The feature gate should prevent introducing new specializations, but not
     // taking advantage of upstream ones.
     if !tcx.sess.features.borrow().specialization &&
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index 87abe681d39..6e2c16c82ae 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -113,9 +113,8 @@ impl<'a, 'gcx, 'tcx> Children {
                                                         possible_sibling,
                                                         impl_def_id);
                 if let Some(impl_header) = overlap {
-                    if tcx.impl_always_allowed_to_overlap(impl_def_id)
-                        && tcx.impl_always_allowed_to_overlap(possible_sibling) {
-                        return Ok((true, true));
+                    if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
+                        return Ok((false, false));
                     }
 
                     let le = specializes(tcx, impl_def_id, possible_sibling);
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index e9bcb80cff2..2ae77046a90 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2227,14 +2227,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         queries::impl_trait_ref::get(self, DUMMY_SP, id)
     }
 
-    /// Returns true if the impl is positive and is for a trait which contains
-    /// no items
-    pub fn impl_always_allowed_to_overlap(self, def_id: DefId) -> bool {
-        self.trait_impl_polarity(def_id) == hir::ImplPolarity::Positive
-            && self.impl_trait_ref(def_id)
-                .map_or(false, |trait_ref| {
-                    self.associated_item_def_ids(trait_ref.def_id).is_empty()
-                })
+    /// Returns true if the impls are the same polarity and are implementing
+    /// a trait which contains no items
+    pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool {
+        let trait1_is_empty = self.impl_trait_ref(def_id1)
+            .map_or(false, |trait_ref| {
+                self.associated_item_def_ids(trait_ref.def_id).is_empty()
+            });
+        let trait2_is_empty = self.impl_trait_ref(def_id2)
+            .map_or(false, |trait_ref| {
+                self.associated_item_def_ids(trait_ref.def_id).is_empty()
+            });
+        self.trait_impl_polarity(def_id1) == self.trait_impl_polarity(def_id2)
+            && trait1_is_empty
+            && trait2_is_empty
     }
 
     // Returns `ty::VariantDef` if `def` refers to a struct,
diff --git a/src/test/compile-fail/auxiliary/trait_impl_conflict.rs b/src/test/compile-fail/auxiliary/trait_impl_conflict.rs
index c3ecbb014dc..3190ce430ad 100644
--- a/src/test/compile-fail/auxiliary/trait_impl_conflict.rs
+++ b/src/test/compile-fail/auxiliary/trait_impl_conflict.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 pub trait Foo {
+    fn foo() {}
 }
 
 impl Foo for isize {