about summary refs log tree commit diff
path: root/src/librustc
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
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')
-rw-r--r--src/librustc/traits/select.rs21
-rw-r--r--src/librustc/ty/mod.rs28
2 files changed, 35 insertions, 14 deletions
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index a54bc05f169..debd946d716 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -50,6 +50,8 @@ use std::iter;
 use std::rc::Rc;
 use crate::util::nodemap::{FxHashMap, FxHashSet};
 
+use syntax::symbol::sym;
+
 pub struct SelectionContext<'cx, 'tcx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
 
@@ -1326,8 +1328,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         (result, dep_node)
     }
 
-    // Treat negative impls as unimplemented
-    fn filter_negative_impls(
+    // Treat negative impls as unimplemented, and reservation impls as Ok(None)
+    fn filter_negative_and_reservation_impls(
         &self,
         candidate: SelectionCandidate<'tcx>,
     ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
@@ -1337,6 +1339,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             {
                 return Err(Unimplemented);
             }
+
+            if self.tcx().has_attr(def_id, sym::rustc_reservation_impl) {
+                return Ok(None);
+            }
         }
         Ok(Some(candidate))
     }
@@ -1453,7 +1459,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // Instead, we select the right impl now but report `Bar does
         // not implement Clone`.
         if candidates.len() == 1 {
-            return self.filter_negative_impls(candidates.pop().unwrap());
+            return self.filter_negative_and_reservation_impls(candidates.pop().unwrap());
         }
 
         // Winnow, but record the exact outcome of evaluation, which
@@ -1528,7 +1534,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
 
         // Just one candidate left.
-        self.filter_negative_impls(candidates.pop().unwrap().candidate)
+        self.filter_negative_and_reservation_impls(candidates.pop().unwrap().candidate)
     }
 
     fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option<Conflict> {
@@ -3728,6 +3734,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             return Err(());
         }
 
+        if self.intercrate.is_none() &&
+            self.tcx().has_attr(impl_def_id, sym::rustc_reservation_impl)
+        {
+            debug!("match_impl: reservation impls only apply in intercrate mode");
+            return Err(());
+        }
+
         debug!("match_impl: success impl_substs={:?}", impl_substs);
         Ok(Normalized {
             value: impl_substs,
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) {