diff options
| author | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2019-07-13 18:02:00 +0300 |
|---|---|---|
| committer | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2019-09-24 21:11:50 +0300 |
| commit | 5d79e8c4c97388dd1201135b8d6cfadccfd3c8e3 (patch) | |
| tree | 374ae8a87cd853e2087688d0d44be613af970d1d /src/librustc | |
| parent | 6ef275e6c3cb1384ec78128eceeb4963ff788dca (diff) | |
| download | rust-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.rs | 21 | ||||
| -rw-r--r-- | src/librustc/ty/mod.rs | 28 |
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) { |
