提交 1ec7ae14 编写于 作者: A Ariel Ben-Yehuda

resolve the rustc_reservation_impl attribute in 1 place

上级 9a94ecde
......@@ -286,7 +286,7 @@
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>> {}
}
......
......@@ -321,7 +321,7 @@ fn evaluate_predicates(
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);
......
......@@ -50,8 +50,6 @@
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 @@ fn filter_negative_and_reservation_impls(
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
{
match self.tcx().impl_polarity(def_id) {
ty::ImplPolarity::Negative if !self.allow_negative_impls => {
return Err(Unimplemented);
}
if self.tcx().has_attr(def_id, sym::rustc_reservation_impl) {
ty::ImplPolarity::Reservation => {
return Ok(None);
}
_ => {}
};
}
Ok(Some(candidate))
}
......@@ -3734,8 +3732,8 @@ fn match_impl(
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(());
......
......@@ -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 @@ pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId)
return Some(ImplOverlapKind::Permitted);
}
if self.impl_polarity(def_id1) != self.impl_polarity(def_id2) {
debug!("impls_are_allowed_to_overlap({:?}, {:?}) - different polarities, 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 @@ pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId)
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.
......
......@@ -722,7 +722,7 @@ pub fn get_parent_impl(&self, id: DefIndex) -> Option<DefId> {
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
}
......
......@@ -1172,8 +1172,9 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
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| {
......
......@@ -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>,
......
......@@ -4,7 +4,7 @@
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();
}
......
......@@ -94,15 +94,18 @@ 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));
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 {
match polarity {
ty::ImplPolarity::Positive => {
check_impl(tcx, item, self_ty, trait_ref);
} else {
}
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,
......@@ -110,6 +113,10 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
auto traits (e.g., `Send` and `Sync`)")
}
}
ty::ImplPolarity::Reservation => {
// FIXME: what amount of WF checking do we need for reservation impls?
}
}
}
hir::ItemKind::Fn(..) => {
check_item_fn(tcx, item);
......@@ -401,7 +408,6 @@ 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(
......@@ -416,7 +422,6 @@ fn check_impl<'tcx>(
fcx.register_predicate(obligation);
}
}
}
None => {
let self_ty = fcx.tcx.type_of(item_def_id);
let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty);
......
......@@ -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),
}
}
......
......@@ -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 @@ fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
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 @@ fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
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 @@ fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
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,
})
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册