diff options
| author | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2019-07-14 00:09:46 +0300 |
|---|---|---|
| committer | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2019-09-24 21:11:50 +0300 |
| commit | 1ec7ae14fa5b4b29f56d7085f632dd6301ad4815 (patch) | |
| tree | cf6cf1ebb1b4001ebeef9f88e07a698be9bd2fcb | |
| parent | 9a94ecde04306986dac1b7ca88b4b327b67ea499 (diff) | |
| download | rust-1ec7ae14fa5b4b29f56d7085f632dd6301ad4815.tar.gz rust-1ec7ae14fa5b4b29f56d7085f632dd6301ad4815.zip | |
resolve the rustc_reservation_impl attribute in 1 place
| -rw-r--r-- | src/librustc/query/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustc/traits/auto_trait.rs | 2 | ||||
| -rw-r--r-- | src/librustc/traits/select.rs | 24 | ||||
| -rw-r--r-- | src/librustc/ty/mod.rs | 46 | ||||
| -rw-r--r-- | src/librustc_metadata/decoder.rs | 2 | ||||
| -rw-r--r-- | src/librustc_metadata/encoder.rs | 3 | ||||
| -rw-r--r-- | src/librustc_metadata/schema.rs | 2 | ||||
| -rw-r--r-- | src/librustc_traits/lowering/mod.rs | 5 | ||||
| -rw-r--r-- | src/librustc_typeck/check/wfcheck.rs | 53 | ||||
| -rw-r--r-- | src/librustc_typeck/collect.rs | 26 | ||||
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 13 |
11 files changed, 112 insertions, 66 deletions
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index c7260945295..b937d1a3040 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -286,7 +286,7 @@ rustc_queries! { query associated_item(_: DefId) -> ty::AssocItem {} query impl_trait_ref(_: DefId) -> Option<ty::TraitRef<'tcx>> {} - query impl_polarity(_: DefId) -> hir::ImplPolarity {} + query impl_polarity(_: DefId) -> ty::ImplPolarity {} query issue33140_self_ty(_: DefId) -> Option<ty::Ty<'tcx>> {} } diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index d89cf8eb3e8..c481943e25e 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -321,7 +321,7 @@ impl AutoTraitFinder<'tcx> { match vtable { Vtable::VtableImpl(VtableImplData { impl_def_id, .. }) => { // Blame tidy for the weird bracket placement - if infcx.tcx.impl_polarity(*impl_def_id) == hir::ImplPolarity::Negative + if infcx.tcx.impl_polarity(*impl_def_id) == ty::ImplPolarity::Negative { debug!("evaluate_nested_obligations: Found explicit negative impl\ {:?}, bailing out", impl_def_id); diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index debd946d716..61bb53dd334 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -50,8 +50,6 @@ 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>, @@ -1334,15 +1332,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidate: SelectionCandidate<'tcx>, ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { if let ImplCandidate(def_id) = candidate { - if !self.allow_negative_impls - && self.tcx().impl_polarity(def_id) == hir::ImplPolarity::Negative - { - return Err(Unimplemented); - } - - if self.tcx().has_attr(def_id, sym::rustc_reservation_impl) { - return Ok(None); - } + match self.tcx().impl_polarity(def_id) { + ty::ImplPolarity::Negative if !self.allow_negative_impls => { + return Err(Unimplemented); + } + ty::ImplPolarity::Reservation => { + return Ok(None); + } + _ => {} + }; } Ok(Some(candidate)) } @@ -3734,8 +3732,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(()); } - if self.intercrate.is_none() && - self.tcx().has_attr(impl_def_id, sym::rustc_reservation_impl) + if self.intercrate.is_none() + && self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation { debug!("match_impl: reservation impls only apply in intercrate mode"); return Err(()); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c5cbe0d0dab..b546a245346 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -167,6 +167,16 @@ pub struct ImplHeader<'tcx> { pub predicates: Vec<Predicate<'tcx>>, } +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)] +pub enum ImplPolarity { + /// `impl Trait for Type` + Positive, + /// `impl !Trait for Type` + Negative, + /// `#[rustc_reservation_impl] impl Trait for Type` + Reservation, +} + #[derive(Copy, Clone, Debug, PartialEq, HashStable)] pub struct AssocItem { pub def_id: DefId, @@ -2911,11 +2921,24 @@ impl<'tcx> TyCtxt<'tcx> { return Some(ImplOverlapKind::Permitted); } - 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; - } + match (self.impl_polarity(def_id1), self.impl_polarity(def_id2)) { + (ImplPolarity::Reservation, _) | + (_, ImplPolarity::Reservation) => { + // `#[rustc_reservation_impl]` impls don't overlap with anything + debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (reservations)", + def_id1, def_id2); + return Some(ImplOverlapKind::Permitted); + } + (ImplPolarity::Positive, ImplPolarity::Negative) | + (ImplPolarity::Negative, ImplPolarity::Positive) => { + // FIXME: when can this happen? + debug!("impls_are_allowed_to_overlap({:?}, {:?}) - None (differing polarities)", + def_id1, def_id2); + return None; + } + (ImplPolarity::Positive, ImplPolarity::Positive) | + (ImplPolarity::Negative, ImplPolarity::Negative) => {} + }; let is_marker_overlap = if self.features().overlapping_marker_traits { let trait1_is_empty = self.impl_trait_ref(def_id1) @@ -2935,15 +2958,10 @@ impl<'tcx> TyCtxt<'tcx> { is_marker_impl(def_id1) && is_marker_impl(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); + if is_marker_overlap { + debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (marker overlap)", + def_id1, def_id2); Some(ImplOverlapKind::Permitted) } else { if let Some(self_ty1) = self.issue33140_self_ty(def_id1) { @@ -3325,7 +3343,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> { debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref); let is_marker_like = - tcx.impl_polarity(def_id) == hir::ImplPolarity::Positive && + tcx.impl_polarity(def_id) == ty::ImplPolarity::Positive && tcx.associated_item_def_ids(trait_ref.def_id).is_empty(); // Check whether these impls would be ok for a marker trait. diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 34c84b1d79d..9785b69eaf0 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -722,7 +722,7 @@ impl<'a, 'tcx> CrateMetadata { self.get_impl_data(id).parent_impl } - pub fn get_impl_polarity(&self, id: DefIndex) -> hir::ImplPolarity { + pub fn get_impl_polarity(&self, id: DefIndex) -> ty::ImplPolarity { self.get_impl_data(id).polarity } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index f430f01542e..9bf0eefd9fe 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1172,8 +1172,9 @@ impl EncodeContext<'tcx> { ctor_sig: None, }), repr_options) } - hir::ItemKind::Impl(_, polarity, defaultness, ..) => { + hir::ItemKind::Impl(_, _, defaultness, ..) => { let trait_ref = tcx.impl_trait_ref(def_id); + let polarity = tcx.impl_polarity(def_id); let parent = if let Some(trait_ref) = trait_ref { let trait_def = tcx.trait_def(trait_ref.def_id); trait_def.ancestors(tcx, def_id).nth(1).and_then(|node| { diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 1a5f0e17ba7..90967c79333 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -327,7 +327,7 @@ pub struct TraitAliasData<'tcx> { #[derive(RustcEncodable, RustcDecodable)] pub struct ImplData<'tcx> { - pub polarity: hir::ImplPolarity, + pub polarity: ty::ImplPolarity, pub defaultness: hir::Defaultness, pub parent_impl: Option<DefId>, diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index 1558ce1bced..51d49f0d59a 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -4,7 +4,7 @@ use rustc::hir::def::DefKind; use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::hir::map::definitions::DefPathData; -use rustc::hir::{self, ImplPolarity}; +use rustc::hir; use rustc::traits::{ Clause, Clauses, @@ -295,7 +295,8 @@ fn program_clauses_for_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> { } fn program_clauses_for_impl(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> { - if let ImplPolarity::Negative = tcx.impl_polarity(def_id) { + // FIXME: implement reservation impls. + if let ty::ImplPolarity::Negative = tcx.impl_polarity(def_id) { return List::empty(); } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 87c34d62bde..e0e878ffdcc 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -94,20 +94,27 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) { // // won't be allowed unless there's an *explicit* implementation of `Send` // for `T` - hir::ItemKind::Impl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => { + hir::ItemKind::Impl(_, _, defaultness, _, ref trait_ref, ref self_ty, _) => { let is_auto = tcx.impl_trait_ref(tcx.hir().local_def_id(item.hir_id)) - .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id)); + .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id)); + let polarity = tcx.impl_polarity(def_id); if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) { tcx.sess.span_err(item.span, "impls of auto traits cannot be default"); } - if polarity == hir::ImplPolarity::Positive { - check_impl(tcx, item, self_ty, trait_ref); - } else { - // FIXME(#27579): what amount of WF checking do we need for neg impls? - if trait_ref.is_some() && !is_auto { - span_err!(tcx.sess, item.span, E0192, - "negative impls are only allowed for \ - auto traits (e.g., `Send` and `Sync`)") + match polarity { + ty::ImplPolarity::Positive => { + check_impl(tcx, item, self_ty, trait_ref); + } + ty::ImplPolarity::Negative => { + // FIXME(#27579): what amount of WF checking do we need for neg impls? + if trait_ref.is_some() && !is_auto { + span_err!(tcx.sess, item.span, E0192, + "negative impls are only allowed for \ + auto traits (e.g., `Send` and `Sync`)") + } + } + ty::ImplPolarity::Reservation => { + // FIXME: what amount of WF checking do we need for reservation impls? } } } @@ -401,20 +408,18 @@ fn check_impl<'tcx>( // `#[rustc_reservation_impl]` impls are not real impls and // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). - if !fcx.tcx.has_attr(item_def_id, sym::rustc_reservation_impl) { - let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap(); - let trait_ref = - fcx.normalize_associated_types_in( - ast_trait_ref.path.span, &trait_ref); - let obligations = - ty::wf::trait_obligations(fcx, - fcx.param_env, - fcx.body_id, - &trait_ref, - ast_trait_ref.path.span); - for obligation in obligations { - fcx.register_predicate(obligation); - } + let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap(); + let trait_ref = + fcx.normalize_associated_types_in( + ast_trait_ref.path.span, &trait_ref); + let obligations = + ty::wf::trait_obligations(fcx, + fcx.param_env, + fcx.body_id, + &trait_ref, + ast_trait_ref.path.span); + for obligation in obligations { + fcx.register_predicate(obligation); } } None => { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d2e9203779c..4503bb264a5 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1866,10 +1866,30 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> { } } -fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> hir::ImplPolarity { +fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - match tcx.hir().expect_item(hir_id).node { - hir::ItemKind::Impl(_, polarity, ..) => polarity, + let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); + let item = tcx.hir().expect_item(hir_id); + match &item.node { + hir::ItemKind::Impl(_, hir::ImplPolarity::Negative, ..) => { + if is_rustc_reservation { + tcx.sess.span_err(item.span, "reservation impls can't be negative"); + } + ty::ImplPolarity::Negative + } + hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, None, _, _) => { + if is_rustc_reservation { + tcx.sess.span_err(item.span, "reservation impls can't be inherent"); + } + ty::ImplPolarity::Positive + } + hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, Some(_tr), _, _) => { + if is_rustc_reservation { + ty::ImplPolarity::Reservation + } else { + ty::ImplPolarity::Positive + } + } ref item => bug!("impl_polarity: {:?} not an impl", item), } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ae70fdc530b..15ada0952c8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3864,11 +3864,13 @@ pub enum ImplPolarity { Negative, } -impl Clean<ImplPolarity> for hir::ImplPolarity { +impl Clean<ImplPolarity> for ty::ImplPolarity { fn clean(&self, _: &DocContext<'_>) -> ImplPolarity { match self { - &hir::ImplPolarity::Positive => ImplPolarity::Positive, - &hir::ImplPolarity::Negative => ImplPolarity::Negative, + &ty::ImplPolarity::Positive | + // FIXME: do we want to do something else here? + &ty::ImplPolarity::Reservation => ImplPolarity::Positive, + &ty::ImplPolarity::Negative => ImplPolarity::Negative, } } } @@ -3900,6 +3902,7 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> { let mut ret = Vec::new(); let trait_ = self.trait_.clean(cx); let items = self.items.iter().map(|ii| ii.clean(cx)).collect::<Vec<_>>(); + let def_id = cx.tcx.hir().local_def_id(self.id); // If this impl block is an implementation of the Deref trait, then we // need to try inlining the target's inherent impl blocks as well. @@ -3918,7 +3921,7 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> { name: None, attrs: self.attrs.clean(cx), source: self.whence.clean(cx), - def_id: cx.tcx.hir().local_def_id(self.id), + def_id, visibility: self.vis.clean(cx), stability: cx.stability(self.id).clean(cx), deprecation: cx.deprecation(self.id).clean(cx), @@ -3929,7 +3932,7 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> { trait_, for_: self.for_.clean(cx), items, - polarity: Some(self.polarity.clean(cx)), + polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)), synthetic: false, blanket_impl: None, }) |
