Skip to content

Commit

Permalink
add error message for case
Browse files Browse the repository at this point in the history
  • Loading branch information
arielb1 committed Sep 24, 2019
1 parent b5665e8 commit 9196b2d
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 8 deletions.
7 changes: 6 additions & 1 deletion src/libcore/convert.rs
Expand Up @@ -556,7 +556,12 @@ impl<T> From<T> for T {

#[stable(feature = "convert_infallible", since = "1.34.0")]
#[cfg(not(boostrap_stdarch_ignore_this))]
#[rustc_reservation_impl]
#[rustc_reservation_impl="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."
]
impl<T> From<!> for T {
fn from(t: !) -> T { t }
}
Expand Down
31 changes: 29 additions & 2 deletions src/librustc/traits/select.rs
Expand Up @@ -43,6 +43,8 @@ use crate::hir;
use rustc_data_structures::bit_set::GrowableBitSet;
use rustc_data_structures::sync::Lock;
use rustc_target::spec::abi::Abi;
use syntax::attr;
use syntax::symbol::sym;
use std::cell::{Cell, RefCell};
use std::cmp;
use std::fmt::{self, Display};
Expand Down Expand Up @@ -99,6 +101,9 @@ pub enum IntercrateAmbiguityCause {
trait_desc: String,
self_desc: Option<String>,
},
ReservationImpl {
message: String
},
}

impl IntercrateAmbiguityCause {
Expand Down Expand Up @@ -139,6 +144,11 @@ impl IntercrateAmbiguityCause {
trait_desc, self_desc
)
}
&IntercrateAmbiguityCause::ReservationImpl {
ref message
} => {
message.clone()
}
}
}
}
Expand Down Expand Up @@ -1328,15 +1338,32 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {

// Treat negative impls as unimplemented, and reservation impls as ambiguity.
fn filter_negative_and_reservation_impls(
&self,
&mut self,
candidate: SelectionCandidate<'tcx>,
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
if let ImplCandidate(def_id) = candidate {
match self.tcx().impl_polarity(def_id) {
let tcx = self.tcx();
match tcx.impl_polarity(def_id) {
ty::ImplPolarity::Negative if !self.allow_negative_impls => {
return Err(Unimplemented);
}
ty::ImplPolarity::Reservation => {
if let Some(intercrate_ambiguity_clauses)
= &mut self.intercrate_ambiguity_causes
{
let attrs = tcx.get_attrs(def_id);
let attr = attr::find_by_name(&attrs, sym::rustc_reservation_impl);
let value = attr.and_then(|a| a.value_str());
if let Some(value) = value {
debug!("filter_negative_and_reservation_impls: \
reservation impl ambiguity on {:?}", def_id);
intercrate_ambiguity_clauses.push(
IntercrateAmbiguityCause::ReservationImpl {
message: value.to_string()
}
);
}
}
return Ok(None);
}
_ => {}
Expand Down
3 changes: 1 addition & 2 deletions src/libsyntax/feature_gate/builtin_attrs.rs
Expand Up @@ -457,7 +457,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
// ==========================================================================
// Internal attributes, Misc:
// ==========================================================================

gated!(
lang, Normal, template!(NameValueStr: "name"), lang_items,
"language items are subject to change",
Expand Down Expand Up @@ -498,7 +497,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
overflow checking behavior of several libcore functions that are inlined \
across crates and will never be stable",
),
rustc_attr!(rustc_reservation_impl, Normal, template!(Word),
rustc_attr!(rustc_reservation_impl, Normal, template!(NameValueStr: "reservation message"),
"the `#[rustc_reservation_impl]` attribute is internally used \
for reserving for `for<T> From<!> for T` impl"
),
Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/never-from-impl-is-reserved.stderr
Expand Up @@ -6,6 +6,8 @@ LL | impl MyTrait for MyFoo {}
LL | // This will conflict with the first impl if we impl `for<T> T: From<!>`.
LL | impl<T> MyTrait for T where T: From<!> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyFoo`
|
= 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.

error: aborting due to previous error

Expand Down
Expand Up @@ -5,7 +5,7 @@
#![feature(rustc_attrs)]

trait MyTrait {}
#[rustc_reservation_impl]
#[rustc_reservation_impl="this impl is reserved"]
impl MyTrait for () {}

trait OtherTrait {}
Expand Down
Expand Up @@ -5,6 +5,8 @@ LL | impl OtherTrait for () {}
| ---------------------- first implementation here
LL | impl<T: MyTrait> OtherTrait for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
|
= note: this impl is reserved

error: aborting due to previous error

Expand Down
Expand Up @@ -5,7 +5,7 @@
#![feature(rustc_attrs)]

trait MyTrait { fn foo(&self); }
#[rustc_reservation_impl]
#[rustc_reservation_impl = "foo"]
impl MyTrait for () { fn foo(&self) {} }

fn main() {
Expand Down
Expand Up @@ -11,7 +11,7 @@ trait MyTrait<S> {
fn foo(&self, s: S) -> usize;
}

#[rustc_reservation_impl]
#[rustc_reservation_impl = "foo"]
impl<T> MyTrait<u64> for T {
fn foo(&self, _x: u64) -> usize { 0 }
}
Expand Down

0 comments on commit 9196b2d

Please sign in to comment.