Skip to content

Commit 53d1fca

Browse files
authored
Rollup merge of rust-lang#62661 - arielb1:never-reserve, r=nikomatsakis
reserve `impl<T> From<!> for T` this is necessary for never-type stabilization. cc rust-lang#57012 rust-lang#35121 I think we wanted a crater run for this @nikomatsakis? r? @nikomatsakis
2 parents a5bc0f0 + e70724c commit 53d1fca

22 files changed

+339
-51
lines changed

Diff for: src/libcore/convert.rs

+12
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,18 @@ impl<T> From<T> for T {
554554
fn from(t: T) -> T { t }
555555
}
556556

557+
/// **Stability note:** This impl does not yet exist, but we are
558+
/// "reserving space" to add it in the future. See
559+
/// [rust-lang/rust#64715][#64715] for details.
560+
///
561+
/// [#64715]: https://github.com/rust-lang/rust/issues/64715
562+
#[stable(feature = "convert_infallible", since = "1.34.0")]
563+
#[cfg(not(bootstrap))]
564+
#[rustc_reservation_impl="permitting this impl would forbid us from adding \
565+
`impl<T> From<!> for T` later; see rust-lang/rust#64715 for details"]
566+
impl<T> From<!> for T {
567+
fn from(t: !) -> T { t }
568+
}
557569

558570
// TryFrom implies TryInto
559571
#[stable(feature = "try_from", since = "1.34.0")]

Diff for: src/librustc/query/mod.rs

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

292292
query impl_trait_ref(_: DefId) -> Option<ty::TraitRef<'tcx>> {}
293-
query impl_polarity(_: DefId) -> hir::ImplPolarity {}
293+
query impl_polarity(_: DefId) -> ty::ImplPolarity {}
294294

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

Diff for: 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);

Diff for: src/librustc/traits/select.rs

+48-10
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ use crate::hir;
4343
use rustc_data_structures::bit_set::GrowableBitSet;
4444
use rustc_data_structures::sync::Lock;
4545
use rustc_target::spec::abi::Abi;
46+
use syntax::attr;
47+
use syntax::symbol::sym;
4648
use std::cell::{Cell, RefCell};
4749
use std::cmp;
4850
use std::fmt::{self, Display};
@@ -99,6 +101,9 @@ pub enum IntercrateAmbiguityCause {
99101
trait_desc: String,
100102
self_desc: Option<String>,
101103
},
104+
ReservationImpl {
105+
message: String
106+
},
102107
}
103108

104109
impl IntercrateAmbiguityCause {
@@ -139,6 +144,11 @@ impl IntercrateAmbiguityCause {
139144
trait_desc, self_desc
140145
)
141146
}
147+
&IntercrateAmbiguityCause::ReservationImpl {
148+
ref message
149+
} => {
150+
message.clone()
151+
}
142152
}
143153
}
144154
}
@@ -1326,17 +1336,38 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13261336
(result, dep_node)
13271337
}
13281338

1329-
// Treat negative impls as unimplemented
1330-
fn filter_negative_impls(
1331-
&self,
1339+
// Treat negative impls as unimplemented, and reservation impls as ambiguity.
1340+
fn filter_negative_and_reservation_impls(
1341+
&mut self,
13321342
candidate: SelectionCandidate<'tcx>,
13331343
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
13341344
if let ImplCandidate(def_id) = candidate {
1335-
if !self.allow_negative_impls
1336-
&& self.tcx().impl_polarity(def_id) == hir::ImplPolarity::Negative
1337-
{
1338-
return Err(Unimplemented);
1339-
}
1345+
let tcx = self.tcx();
1346+
match tcx.impl_polarity(def_id) {
1347+
ty::ImplPolarity::Negative if !self.allow_negative_impls => {
1348+
return Err(Unimplemented);
1349+
}
1350+
ty::ImplPolarity::Reservation => {
1351+
if let Some(intercrate_ambiguity_clauses)
1352+
= &mut self.intercrate_ambiguity_causes
1353+
{
1354+
let attrs = tcx.get_attrs(def_id);
1355+
let attr = attr::find_by_name(&attrs, sym::rustc_reservation_impl);
1356+
let value = attr.and_then(|a| a.value_str());
1357+
if let Some(value) = value {
1358+
debug!("filter_negative_and_reservation_impls: \
1359+
reservation impl ambiguity on {:?}", def_id);
1360+
intercrate_ambiguity_clauses.push(
1361+
IntercrateAmbiguityCause::ReservationImpl {
1362+
message: value.to_string()
1363+
}
1364+
);
1365+
}
1366+
}
1367+
return Ok(None);
1368+
}
1369+
_ => {}
1370+
};
13401371
}
13411372
Ok(Some(candidate))
13421373
}
@@ -1453,7 +1484,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14531484
// Instead, we select the right impl now but report `Bar does
14541485
// not implement Clone`.
14551486
if candidates.len() == 1 {
1456-
return self.filter_negative_impls(candidates.pop().unwrap());
1487+
return self.filter_negative_and_reservation_impls(candidates.pop().unwrap());
14571488
}
14581489

14591490
// Winnow, but record the exact outcome of evaluation, which
@@ -1528,7 +1559,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15281559
}
15291560

15301561
// Just one candidate left.
1531-
self.filter_negative_impls(candidates.pop().unwrap().candidate)
1562+
self.filter_negative_and_reservation_impls(candidates.pop().unwrap().candidate)
15321563
}
15331564

15341565
fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option<Conflict> {
@@ -3728,6 +3759,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
37283759
return Err(());
37293760
}
37303761

3762+
if self.intercrate.is_none()
3763+
&& self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
3764+
{
3765+
debug!("match_impl: reservation impls only apply in intercrate mode");
3766+
return Err(());
3767+
}
3768+
37313769
debug!("match_impl: success impl_substs={:?}", impl_substs);
37323770
Ok(Normalized {
37333771
value: impl_substs,

Diff for: src/librustc/ty/mod.rs

+40-11
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,19 @@ pub struct ImplHeader<'tcx> {
167167
pub predicates: Vec<Predicate<'tcx>>,
168168
}
169169

170+
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
171+
pub enum ImplPolarity {
172+
/// `impl Trait for Type`
173+
Positive,
174+
/// `impl !Trait for Type`
175+
Negative,
176+
/// `#[rustc_reservation_impl] impl Trait for Type`
177+
///
178+
/// This is a "stability hack", not a real Rust feature.
179+
/// See #64631 for details.
180+
Reservation,
181+
}
182+
170183
#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
171184
pub struct AssocItem {
172185
pub def_id: DefId,
@@ -2911,7 +2924,26 @@ impl<'tcx> TyCtxt<'tcx> {
29112924
return Some(ImplOverlapKind::Permitted);
29122925
}
29132926

2914-
let is_legit = if self.features().overlapping_marker_traits {
2927+
match (self.impl_polarity(def_id1), self.impl_polarity(def_id2)) {
2928+
(ImplPolarity::Reservation, _) |
2929+
(_, ImplPolarity::Reservation) => {
2930+
// `#[rustc_reservation_impl]` impls don't overlap with anything
2931+
debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (reservations)",
2932+
def_id1, def_id2);
2933+
return Some(ImplOverlapKind::Permitted);
2934+
}
2935+
(ImplPolarity::Positive, ImplPolarity::Negative) |
2936+
(ImplPolarity::Negative, ImplPolarity::Positive) => {
2937+
// `impl AutoTrait for Type` + `impl !AutoTrait for Type`
2938+
debug!("impls_are_allowed_to_overlap({:?}, {:?}) - None (differing polarities)",
2939+
def_id1, def_id2);
2940+
return None;
2941+
}
2942+
(ImplPolarity::Positive, ImplPolarity::Positive) |
2943+
(ImplPolarity::Negative, ImplPolarity::Negative) => {}
2944+
};
2945+
2946+
let is_marker_overlap = if self.features().overlapping_marker_traits {
29152947
let trait1_is_empty = self.impl_trait_ref(def_id1)
29162948
.map_or(false, |trait_ref| {
29172949
self.associated_item_def_ids(trait_ref.def_id).is_empty()
@@ -2920,22 +2952,19 @@ impl<'tcx> TyCtxt<'tcx> {
29202952
.map_or(false, |trait_ref| {
29212953
self.associated_item_def_ids(trait_ref.def_id).is_empty()
29222954
});
2923-
self.impl_polarity(def_id1) == self.impl_polarity(def_id2)
2924-
&& trait1_is_empty
2925-
&& trait2_is_empty
2955+
trait1_is_empty && trait2_is_empty
29262956
} else {
29272957
let is_marker_impl = |def_id: DefId| -> bool {
29282958
let trait_ref = self.impl_trait_ref(def_id);
29292959
trait_ref.map_or(false, |tr| self.trait_def(tr.def_id).is_marker)
29302960
};
2931-
self.impl_polarity(def_id1) == self.impl_polarity(def_id2)
2932-
&& is_marker_impl(def_id1)
2933-
&& is_marker_impl(def_id2)
2961+
is_marker_impl(def_id1) && is_marker_impl(def_id2)
29342962
};
29352963

2936-
if is_legit {
2937-
debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted)",
2938-
def_id1, def_id2);
2964+
2965+
if is_marker_overlap {
2966+
debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (marker overlap)",
2967+
def_id1, def_id2);
29392968
Some(ImplOverlapKind::Permitted)
29402969
} else {
29412970
if let Some(self_ty1) = self.issue33140_self_ty(def_id1) {
@@ -3317,7 +3346,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
33173346
debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref);
33183347

33193348
let is_marker_like =
3320-
tcx.impl_polarity(def_id) == hir::ImplPolarity::Positive &&
3349+
tcx.impl_polarity(def_id) == ty::ImplPolarity::Positive &&
33213350
tcx.associated_item_def_ids(trait_ref.def_id).is_empty();
33223351

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

Diff for: src/librustc_metadata/decoder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ impl<'a, 'tcx> CrateMetadata {
722722
self.get_impl_data(id).parent_impl
723723
}
724724

725-
pub fn get_impl_polarity(&self, id: DefIndex) -> hir::ImplPolarity {
725+
pub fn get_impl_polarity(&self, id: DefIndex) -> ty::ImplPolarity {
726726
self.get_impl_data(id).polarity
727727
}
728728

Diff for: src/librustc_metadata/encoder.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1175,8 +1175,9 @@ impl EncodeContext<'tcx> {
11751175
ctor_sig: None,
11761176
}), repr_options)
11771177
}
1178-
hir::ItemKind::Impl(_, polarity, defaultness, ..) => {
1178+
hir::ItemKind::Impl(_, _, defaultness, ..) => {
11791179
let trait_ref = tcx.impl_trait_ref(def_id);
1180+
let polarity = tcx.impl_polarity(def_id);
11801181
let parent = if let Some(trait_ref) = trait_ref {
11811182
let trait_def = tcx.trait_def(trait_ref.def_id);
11821183
trait_def.ancestors(tcx, def_id).nth(1).and_then(|node| {

Diff for: src/librustc_metadata/schema.rs

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

329329
#[derive(RustcEncodable, RustcDecodable)]
330330
pub struct ImplData<'tcx> {
331-
pub polarity: hir::ImplPolarity,
331+
pub polarity: ty::ImplPolarity,
332332
pub defaultness: hir::Defaultness,
333333
pub parent_impl: Option<DefId>,
334334

Diff for: src/librustc_traits/lowering/mod.rs

+2-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,7 @@ 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+
if let ty::ImplPolarity::Negative = tcx.impl_polarity(def_id) {
299299
return List::empty();
300300
}
301301

Diff for: src/librustc_typeck/check/wfcheck.rs

+24-14
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
}
@@ -398,16 +405,19 @@ fn check_impl<'tcx>(
398405

399406
match *ast_trait_ref {
400407
Some(ref ast_trait_ref) => {
408+
// `#[rustc_reservation_impl]` impls are not real impls and
409+
// therefore don't need to be WF (the trait's `Self: Trait` predicate
410+
// won't hold).
401411
let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap();
402412
let trait_ref =
403413
fcx.normalize_associated_types_in(
404414
ast_trait_ref.path.span, &trait_ref);
405415
let obligations =
406416
ty::wf::trait_obligations(fcx,
407-
fcx.param_env,
408-
fcx.body_id,
409-
&trait_ref,
410-
ast_trait_ref.path.span);
417+
fcx.param_env,
418+
fcx.body_id,
419+
&trait_ref,
420+
ast_trait_ref.path.span);
411421
for obligation in obligations {
412422
fcx.register_predicate(obligation);
413423
}

Diff for: src/librustc_typeck/collect.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -1889,10 +1889,30 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
18891889
}
18901890
}
18911891

1892-
fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> hir::ImplPolarity {
1892+
fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
18931893
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
1894-
match tcx.hir().expect_item(hir_id).node {
1895-
hir::ItemKind::Impl(_, polarity, ..) => polarity,
1894+
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
1895+
let item = tcx.hir().expect_item(hir_id);
1896+
match &item.node {
1897+
hir::ItemKind::Impl(_, hir::ImplPolarity::Negative, ..) => {
1898+
if is_rustc_reservation {
1899+
tcx.sess.span_err(item.span, "reservation impls can't be negative");
1900+
}
1901+
ty::ImplPolarity::Negative
1902+
}
1903+
hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, None, _, _) => {
1904+
if is_rustc_reservation {
1905+
tcx.sess.span_err(item.span, "reservation impls can't be inherent");
1906+
}
1907+
ty::ImplPolarity::Positive
1908+
}
1909+
hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, Some(_tr), _, _) => {
1910+
if is_rustc_reservation {
1911+
ty::ImplPolarity::Reservation
1912+
} else {
1913+
ty::ImplPolarity::Positive
1914+
}
1915+
}
18961916
ref item => bug!("impl_polarity: {:?} not an impl", item),
18971917
}
18981918
}

0 commit comments

Comments
 (0)