about summary refs log tree commit diff
path: root/src/librustc/ty
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2019-07-13 18:02:00 +0300
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2019-09-24 21:11:50 +0300
commit5d79e8c4c97388dd1201135b8d6cfadccfd3c8e3 (patch)
tree374ae8a87cd853e2087688d0d44be613af970d1d /src/librustc/ty
parent6ef275e6c3cb1384ec78128eceeb4963ff788dca (diff)
downloadrust-5d79e8c4c97388dd1201135b8d6cfadccfd3c8e3.tar.gz
rust-5d79e8c4c97388dd1201135b8d6cfadccfd3c8e3.zip
reserve `impl<T> From<!> for T`
this is necessary for never-type stabilization
Diffstat (limited to 'src/librustc/ty')
-rw-r--r--src/librustc/ty/mod.rs28
1 files changed, 18 insertions, 10 deletions
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 8bb9648e031..c5cbe0d0dab 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2911,7 +2911,13 @@ impl<'tcx> TyCtxt<'tcx> {
             return Some(ImplOverlapKind::Permitted);
         }
 
-        let is_legit = if self.features().overlapping_marker_traits {
+        if self.impl_polarity(def_id1) != self.impl_polarity(def_id2) {
+            debug!("impls_are_allowed_to_overlap({:?}, {:?}) - different polarities, None",
+                   def_id1, def_id2);
+            return None;
+        }
+
+        let is_marker_overlap = if self.features().overlapping_marker_traits {
             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()
@@ -2920,22 +2926,24 @@ impl<'tcx> TyCtxt<'tcx> {
                 .map_or(false, |trait_ref| {
                     self.associated_item_def_ids(trait_ref.def_id).is_empty()
                 });
-            self.impl_polarity(def_id1) == self.impl_polarity(def_id2)
-                && trait1_is_empty
-                && trait2_is_empty
+            trait1_is_empty && trait2_is_empty
         } else {
             let is_marker_impl = |def_id: DefId| -> bool {
                 let trait_ref = self.impl_trait_ref(def_id);
                 trait_ref.map_or(false, |tr| self.trait_def(tr.def_id).is_marker)
             };
-            self.impl_polarity(def_id1) == self.impl_polarity(def_id2)
-                && is_marker_impl(def_id1)
-                && is_marker_impl(def_id2)
+            is_marker_impl(def_id1) && is_marker_impl(def_id2)
         };
 
-        if is_legit {
-            debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted)",
-                  def_id1, def_id2);
+        // `#[rustc_reservation_impl]` impls don't overlap with anything
+        let is_reserve_overlap = {
+            self.has_attr(def_id1, sym::rustc_reservation_impl) ||
+            self.has_attr(def_id2, sym::rustc_reservation_impl)
+        };
+
+        if is_marker_overlap || is_reserve_overlap {
+            debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) ({:?}/{:?})",
+                  def_id1, def_id2, is_marker_overlap, is_reserve_overlap);
             Some(ImplOverlapKind::Permitted)
         } else {
             if let Some(self_ty1) = self.issue33140_self_ty(def_id1) {