Skip to content

Commit 595c2e6

Browse files
committed
add error message for case
1 parent 2686a90 commit 595c2e6

8 files changed

+48
-11
lines changed

src/libcore/convert.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,12 @@ impl<T> From<T> for T {
548548

549549
#[stable(feature = "convert_infallible", since = "1.34.0")]
550550
#[cfg(not(bootstrap))]
551-
#[rustc_reservation_impl]
551+
#[rustc_reservation_impl="a future version of Rust might implement `From<!>` for \
552+
all types. \
553+
However, it is OK to implement `From<!>` for types you own - \
554+
when the blanket impl will be added, coherence will be changed \
555+
to make these impls not be an error."
556+
]
552557
impl<T> From<!> for T {
553558
fn from(t: !) -> T { t }
554559
}

src/librustc/traits/select.rs

+29-2
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
}
@@ -1327,15 +1337,32 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13271337

13281338
// Treat negative impls as unimplemented, and reservation impls as ambiguity.
13291339
fn filter_negative_and_reservation_impls(
1330-
&self,
1340+
&mut self,
13311341
candidate: SelectionCandidate<'tcx>,
13321342
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
13331343
if let ImplCandidate(def_id) = candidate {
1334-
match self.tcx().impl_polarity(def_id) {
1344+
let tcx = self.tcx();
1345+
match tcx.impl_polarity(def_id) {
13351346
ty::ImplPolarity::Negative if !self.allow_negative_impls => {
13361347
return Err(Unimplemented);
13371348
}
13381349
ty::ImplPolarity::Reservation => {
1350+
if let Some(intercrate_ambiguity_clauses)
1351+
= &mut self.intercrate_ambiguity_causes
1352+
{
1353+
let attrs = tcx.get_attrs(def_id);
1354+
let attr = attr::find_by_name(&attrs, sym::rustc_reservation_impl);
1355+
let value = attr.and_then(|a| a.value_str());
1356+
if let Some(value) = value {
1357+
debug!("filter_negative_and_reservation_impls: \
1358+
reservation impl ambiguity on {:?}", def_id);
1359+
intercrate_ambiguity_clauses.push(
1360+
IntercrateAmbiguityCause::ReservationImpl {
1361+
message: value.to_string()
1362+
}
1363+
);
1364+
}
1365+
}
13391366
return Ok(None);
13401367
}
13411368
_ => {}

src/libsyntax/feature_gate.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -1276,11 +1276,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
12761276
attribute is just used for rustc unit \
12771277
tests and will never be stable",
12781278
cfg_fn!(rustc_attrs))),
1279-
(sym::rustc_reservation_impl, Normal, template!(Word), Gated(Stability::Unstable,
1280-
sym::rustc_attrs,
1281-
"internal rustc attributes \
1282-
will never be stable",
1283-
cfg_fn!(rustc_attrs))),
1279+
(sym::rustc_reservation_impl, Normal, template!(NameValueStr: "reservation message"),
1280+
Gated(Stability::Unstable,
1281+
sym::rustc_attrs,
1282+
"internal rustc attributes \
1283+
will never be stable",
1284+
cfg_fn!(rustc_attrs))),
12841285
(sym::rustc_test_marker, Normal, template!(Word), Gated(Stability::Unstable,
12851286
sym::rustc_attrs,
12861287
"the `#[rustc_test_marker]` attribute \

src/test/ui/never-from-impl-is-reserved.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ LL | impl MyTrait for MyFoo {}
66
LL | // This will conflict with the first impl if we impl `for<T> T: From<!>`.
77
LL | impl<T> MyTrait for T where T: From<!> {}
88
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyFoo`
9+
|
10+
= note: a future version of Rust might implement `From<!>` for all types. However, it is OK to implement `From<!>` for types you own - when the blanket impl will be added, coherence will be changed to make these impls not be an error.
911

1012
error: aborting due to previous error
1113

src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#![feature(rustc_attrs)]
66

77
trait MyTrait {}
8-
#[rustc_reservation_impl]
8+
#[rustc_reservation_impl="this impl is reserved"]
99
impl MyTrait for () {}
1010

1111
trait OtherTrait {}

src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ LL | impl OtherTrait for () {}
55
| ---------------------- first implementation here
66
LL | impl<T: MyTrait> OtherTrait for T {}
77
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
8+
|
9+
= note: this impl is reserved
810

911
error: aborting due to previous error
1012

src/test/ui/traits/reservation-impls/reservation-impl-no-use.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#![feature(rustc_attrs)]
66

77
trait MyTrait { fn foo(&self); }
8-
#[rustc_reservation_impl]
8+
#[rustc_reservation_impl = "foo"]
99
impl MyTrait for () { fn foo(&self) {} }
1010

1111
fn main() {

src/test/ui/traits/reservation-impls/reservation-impl-ok.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ trait MyTrait<S> {
1111
fn foo(&self, s: S) -> usize;
1212
}
1313

14-
#[rustc_reservation_impl]
14+
#[rustc_reservation_impl = "foo"]
1515
impl<T> MyTrait<u64> for T {
1616
fn foo(&self, _x: u64) -> usize { 0 }
1717
}

0 commit comments

Comments
 (0)