Skip to content

Commit ed6db36

Browse files
committed
resolve the rustc_reservation_impl attribute in 1 place
1 parent f358152 commit ed6db36

File tree

11 files changed

+112
-66
lines changed

11 files changed

+112
-66
lines changed

src/librustc/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ rustc_queries! {
273273
query associated_item(_: DefId) -> ty::AssocItem {}
274274

275275
query impl_trait_ref(_: DefId) -> Option<ty::TraitRef<'tcx>> {}
276-
query impl_polarity(_: DefId) -> hir::ImplPolarity {}
276+
query impl_polarity(_: DefId) -> ty::ImplPolarity {}
277277

278278
query issue33140_self_ty(_: DefId) -> Option<ty::Ty<'tcx>> {}
279279
}

src/librustc/traits/auto_trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ impl AutoTraitFinder<'tcx> {
321321
match vtable {
322322
Vtable::VtableImpl(VtableImplData { impl_def_id, .. }) => {
323323
// Blame tidy for the weird bracket placement
324-
if infcx.tcx.impl_polarity(*impl_def_id) == hir::ImplPolarity::Negative
324+
if infcx.tcx.impl_polarity(*impl_def_id) == ty::ImplPolarity::Negative
325325
{
326326
debug!("evaluate_nested_obligations: Found explicit negative impl\
327327
{:?}, bailing out", impl_def_id);

src/librustc/traits/select.rs

+11-13
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ use std::iter;
5050
use std::rc::Rc;
5151
use crate::util::nodemap::{FxHashMap, FxHashSet};
5252

53-
use syntax::symbol::sym;
54-
5553
pub struct SelectionContext<'cx, 'tcx> {
5654
infcx: &'cx InferCtxt<'cx, 'tcx>,
5755

@@ -1333,15 +1331,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13331331
candidate: SelectionCandidate<'tcx>,
13341332
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
13351333
if let ImplCandidate(def_id) = candidate {
1336-
if !self.allow_negative_impls
1337-
&& self.tcx().impl_polarity(def_id) == hir::ImplPolarity::Negative
1338-
{
1339-
return Err(Unimplemented);
1340-
}
1341-
1342-
if self.tcx().has_attr(def_id, sym::rustc_reservation_impl) {
1343-
return Ok(None);
1344-
}
1334+
match self.tcx().impl_polarity(def_id) {
1335+
ty::ImplPolarity::Negative if !self.allow_negative_impls => {
1336+
return Err(Unimplemented);
1337+
}
1338+
ty::ImplPolarity::Reservation => {
1339+
return Ok(None);
1340+
}
1341+
_ => {}
1342+
};
13451343
}
13461344
Ok(Some(candidate))
13471345
}
@@ -3733,8 +3731,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
37333731
return Err(());
37343732
}
37353733

3736-
if self.intercrate.is_none() &&
3737-
self.tcx().has_attr(impl_def_id, sym::rustc_reservation_impl)
3734+
if self.intercrate.is_none()
3735+
&& self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
37383736
{
37393737
debug!("match_impl: reservation impls only apply in intercrate mode");
37403738
return Err(());

src/librustc/ty/mod.rs

+32-14
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,16 @@ pub struct ImplHeader<'tcx> {
166166
pub predicates: Vec<Predicate<'tcx>>,
167167
}
168168

169+
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
170+
pub enum ImplPolarity {
171+
/// `impl Trait for Type`
172+
Positive,
173+
/// `impl !Trait for Type`
174+
Negative,
175+
/// `#[rustc_reservation_impl] impl Trait for Type`
176+
Reservation,
177+
}
178+
169179
#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
170180
pub struct AssocItem {
171181
pub def_id: DefId,
@@ -2892,11 +2902,24 @@ impl<'tcx> TyCtxt<'tcx> {
28922902
pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId)
28932903
-> Option<ImplOverlapKind>
28942904
{
2895-
if self.impl_polarity(def_id1) != self.impl_polarity(def_id2) {
2896-
debug!("impls_are_allowed_to_overlap({:?}, {:?}) - different polarities, None",
2897-
def_id1, def_id2);
2898-
return None;
2899-
}
2905+
match (self.impl_polarity(def_id1), self.impl_polarity(def_id2)) {
2906+
(ImplPolarity::Reservation, _) |
2907+
(_, ImplPolarity::Reservation) => {
2908+
// `#[rustc_reservation_impl]` impls don't overlap with anything
2909+
debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (reservations)",
2910+
def_id1, def_id2);
2911+
return Some(ImplOverlapKind::Permitted);
2912+
}
2913+
(ImplPolarity::Positive, ImplPolarity::Negative) |
2914+
(ImplPolarity::Negative, ImplPolarity::Positive) => {
2915+
// FIXME: when can this happen?
2916+
debug!("impls_are_allowed_to_overlap({:?}, {:?}) - None (differing polarities)",
2917+
def_id1, def_id2);
2918+
return None;
2919+
}
2920+
(ImplPolarity::Positive, ImplPolarity::Positive) |
2921+
(ImplPolarity::Negative, ImplPolarity::Negative) => {}
2922+
};
29002923

29012924
let is_marker_overlap = if self.features().overlapping_marker_traits {
29022925
let trait1_is_empty = self.impl_trait_ref(def_id1)
@@ -2916,15 +2939,10 @@ impl<'tcx> TyCtxt<'tcx> {
29162939
is_marker_impl(def_id1) && is_marker_impl(def_id2)
29172940
};
29182941

2919-
// `#[rustc_reservation_impl]` impls don't overlap with anything
2920-
let is_reserve_overlap = {
2921-
self.has_attr(def_id1, sym::rustc_reservation_impl) ||
2922-
self.has_attr(def_id2, sym::rustc_reservation_impl)
2923-
};
29242942

2925-
if is_marker_overlap || is_reserve_overlap {
2926-
debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) ({:?}/{:?})",
2927-
def_id1, def_id2, is_marker_overlap, is_reserve_overlap);
2943+
if is_marker_overlap {
2944+
debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (marker overlap)",
2945+
def_id1, def_id2);
29282946
Some(ImplOverlapKind::Permitted)
29292947
} else {
29302948
if let Some(self_ty1) = self.issue33140_self_ty(def_id1) {
@@ -3306,7 +3324,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
33063324
debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref);
33073325

33083326
let is_marker_like =
3309-
tcx.impl_polarity(def_id) == hir::ImplPolarity::Positive &&
3327+
tcx.impl_polarity(def_id) == ty::ImplPolarity::Positive &&
33103328
tcx.associated_item_def_ids(trait_ref.def_id).is_empty();
33113329

33123330
// Check whether these impls would be ok for a marker trait.

src/librustc_metadata/decoder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ impl<'a, 'tcx> CrateMetadata {
686686
self.get_impl_data(id).parent_impl
687687
}
688688

689-
pub fn get_impl_polarity(&self, id: DefIndex) -> hir::ImplPolarity {
689+
pub fn get_impl_polarity(&self, id: DefIndex) -> ty::ImplPolarity {
690690
self.get_impl_data(id).polarity
691691
}
692692

src/librustc_metadata/encoder.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1126,8 +1126,9 @@ impl EncodeContext<'tcx> {
11261126
ctor_sig: None,
11271127
}), repr_options)
11281128
}
1129-
hir::ItemKind::Impl(_, polarity, defaultness, ..) => {
1129+
hir::ItemKind::Impl(_, _, defaultness, ..) => {
11301130
let trait_ref = tcx.impl_trait_ref(def_id);
1131+
let polarity = tcx.impl_polarity(def_id);
11311132
let parent = if let Some(trait_ref) = trait_ref {
11321133
let trait_def = tcx.trait_def(trait_ref.def_id);
11331134
trait_def.ancestors(tcx, def_id).nth(1).and_then(|node| {

src/librustc_metadata/schema.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ pub struct TraitAliasData<'tcx> {
317317

318318
#[derive(RustcEncodable, RustcDecodable)]
319319
pub struct ImplData<'tcx> {
320-
pub polarity: hir::ImplPolarity,
320+
pub polarity: ty::ImplPolarity,
321321
pub defaultness: hir::Defaultness,
322322
pub parent_impl: Option<DefId>,
323323

src/librustc_traits/lowering/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc::hir::def::DefKind;
44
use rustc::hir::def_id::DefId;
55
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
66
use rustc::hir::map::definitions::DefPathData;
7-
use rustc::hir::{self, ImplPolarity};
7+
use rustc::hir;
88
use rustc::traits::{
99
Clause,
1010
Clauses,
@@ -295,7 +295,8 @@ fn program_clauses_for_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
295295
}
296296

297297
fn program_clauses_for_impl(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> {
298-
if let ImplPolarity::Negative = tcx.impl_polarity(def_id) {
298+
// FIXME: implement reservation impls.
299+
if let ty::ImplPolarity::Negative = tcx.impl_polarity(def_id) {
299300
return List::empty();
300301
}
301302

src/librustc_typeck/check/wfcheck.rs

+29-24
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,27 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
9494
//
9595
// won't be allowed unless there's an *explicit* implementation of `Send`
9696
// for `T`
97-
hir::ItemKind::Impl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => {
97+
hir::ItemKind::Impl(_, _, defaultness, _, ref trait_ref, ref self_ty, _) => {
9898
let is_auto = tcx.impl_trait_ref(tcx.hir().local_def_id(item.hir_id))
99-
.map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
99+
.map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
100+
let polarity = tcx.impl_polarity(def_id);
100101
if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) {
101102
tcx.sess.span_err(item.span, "impls of auto traits cannot be default");
102103
}
103-
if polarity == hir::ImplPolarity::Positive {
104-
check_impl(tcx, item, self_ty, trait_ref);
105-
} else {
106-
// FIXME(#27579): what amount of WF checking do we need for neg impls?
107-
if trait_ref.is_some() && !is_auto {
108-
span_err!(tcx.sess, item.span, E0192,
109-
"negative impls are only allowed for \
110-
auto traits (e.g., `Send` and `Sync`)")
104+
match polarity {
105+
ty::ImplPolarity::Positive => {
106+
check_impl(tcx, item, self_ty, trait_ref);
107+
}
108+
ty::ImplPolarity::Negative => {
109+
// FIXME(#27579): what amount of WF checking do we need for neg impls?
110+
if trait_ref.is_some() && !is_auto {
111+
span_err!(tcx.sess, item.span, E0192,
112+
"negative impls are only allowed for \
113+
auto traits (e.g., `Send` and `Sync`)")
114+
}
115+
}
116+
ty::ImplPolarity::Reservation => {
117+
// FIXME: what amount of WF checking do we need for reservation impls?
111118
}
112119
}
113120
}
@@ -402,20 +409,18 @@ fn check_impl<'tcx>(
402409
// `#[rustc_reservation_impl]` impls are not real impls and
403410
// therefore don't need to be WF (the trait's `Self: Trait` predicate
404411
// won't hold).
405-
if !fcx.tcx.has_attr(item_def_id, sym::rustc_reservation_impl) {
406-
let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
407-
let trait_ref =
408-
fcx.normalize_associated_types_in(
409-
ast_trait_ref.path.span, &trait_ref);
410-
let obligations =
411-
ty::wf::trait_obligations(fcx,
412-
fcx.param_env,
413-
fcx.body_id,
414-
&trait_ref,
415-
ast_trait_ref.path.span);
416-
for obligation in obligations {
417-
fcx.register_predicate(obligation);
418-
}
412+
let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
413+
let trait_ref =
414+
fcx.normalize_associated_types_in(
415+
ast_trait_ref.path.span, &trait_ref);
416+
let obligations =
417+
ty::wf::trait_obligations(fcx,
418+
fcx.param_env,
419+
fcx.body_id,
420+
&trait_ref,
421+
ast_trait_ref.path.span);
422+
for obligation in obligations {
423+
fcx.register_predicate(obligation);
419424
}
420425
}
421426
None => {

src/librustc_typeck/collect.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -1863,10 +1863,30 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
18631863
}
18641864
}
18651865

1866-
fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> hir::ImplPolarity {
1866+
fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
18671867
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
1868-
match tcx.hir().expect_item(hir_id).node {
1869-
hir::ItemKind::Impl(_, polarity, ..) => polarity,
1868+
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
1869+
let item = tcx.hir().expect_item(hir_id);
1870+
match &item.node {
1871+
hir::ItemKind::Impl(_, hir::ImplPolarity::Negative, ..) => {
1872+
if is_rustc_reservation {
1873+
tcx.sess.span_err(item.span, "reservation impls can't be negative");
1874+
}
1875+
ty::ImplPolarity::Negative
1876+
}
1877+
hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, None, _, _) => {
1878+
if is_rustc_reservation {
1879+
tcx.sess.span_err(item.span, "reservation impls can't be inherent");
1880+
}
1881+
ty::ImplPolarity::Positive
1882+
}
1883+
hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, Some(_tr), _, _) => {
1884+
if is_rustc_reservation {
1885+
ty::ImplPolarity::Reservation
1886+
} else {
1887+
ty::ImplPolarity::Positive
1888+
}
1889+
}
18701890
ref item => bug!("impl_polarity: {:?} not an impl", item),
18711891
}
18721892
}

src/librustdoc/clean/mod.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -3768,11 +3768,13 @@ pub enum ImplPolarity {
37683768
Negative,
37693769
}
37703770

3771-
impl Clean<ImplPolarity> for hir::ImplPolarity {
3771+
impl Clean<ImplPolarity> for ty::ImplPolarity {
37723772
fn clean(&self, _: &DocContext<'_>) -> ImplPolarity {
37733773
match self {
3774-
&hir::ImplPolarity::Positive => ImplPolarity::Positive,
3775-
&hir::ImplPolarity::Negative => ImplPolarity::Negative,
3774+
&ty::ImplPolarity::Positive |
3775+
// FIXME: do we want to do something else here?
3776+
&ty::ImplPolarity::Reservation => ImplPolarity::Positive,
3777+
&ty::ImplPolarity::Negative => ImplPolarity::Negative,
37763778
}
37773779
}
37783780
}
@@ -3804,6 +3806,7 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> {
38043806
let mut ret = Vec::new();
38053807
let trait_ = self.trait_.clean(cx);
38063808
let items = self.items.iter().map(|ii| ii.clean(cx)).collect::<Vec<_>>();
3809+
let def_id = cx.tcx.hir().local_def_id(self.id);
38073810

38083811
// If this impl block is an implementation of the Deref trait, then we
38093812
// need to try inlining the target's inherent impl blocks as well.
@@ -3822,7 +3825,7 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> {
38223825
name: None,
38233826
attrs: self.attrs.clean(cx),
38243827
source: self.whence.clean(cx),
3825-
def_id: cx.tcx.hir().local_def_id(self.id),
3828+
def_id,
38263829
visibility: self.vis.clean(cx),
38273830
stability: self.stab.clean(cx),
38283831
deprecation: self.depr.clean(cx),
@@ -3833,7 +3836,7 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> {
38333836
trait_,
38343837
for_: self.for_.clean(cx),
38353838
items,
3836-
polarity: Some(self.polarity.clean(cx)),
3839+
polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)),
38373840
synthetic: false,
38383841
blanket_impl: None,
38393842
})

0 commit comments

Comments
 (0)