Add rustc_deny_explicit_impl
This commit is contained in:
parent
742d3f02c2
commit
b5b6467810
6 changed files with 28 additions and 50 deletions
|
@ -1,4 +1,5 @@
|
||||||
The `Sized` trait was implemented explicitly.
|
A built-in trait was implemented explicitly. All implementations of the trait
|
||||||
|
are provided automatically by the compiler.
|
||||||
|
|
||||||
Erroneous code example:
|
Erroneous code example:
|
||||||
|
|
||||||
|
|
|
@ -691,6 +691,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true,
|
rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true,
|
||||||
"#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl."
|
"#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl."
|
||||||
),
|
),
|
||||||
|
rustc_attr!(
|
||||||
|
rustc_deny_explicit_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: false,
|
||||||
|
"#[rustc_deny_explicit_impl] enforces that a trait can have no user-provided impls"
|
||||||
|
),
|
||||||
rustc_attr!(
|
rustc_attr!(
|
||||||
rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word), ErrorFollowing,
|
rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word), ErrorFollowing,
|
||||||
"#[rustc_has_incoherent_inherent_impls] allows the addition of incoherent inherent impls for \
|
"#[rustc_has_incoherent_inherent_impls] allows the addition of incoherent inherent impls for \
|
||||||
|
|
|
@ -5,10 +5,11 @@
|
||||||
// done by the orphan and overlap modules. Then we build up various
|
// done by the orphan and overlap modules. Then we build up various
|
||||||
// mappings. That mapping code resides here.
|
// mappings. That mapping code resides here.
|
||||||
|
|
||||||
use rustc_errors::struct_span_err;
|
use rustc_errors::{error_code, struct_span_err};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
|
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
|
||||||
|
use rustc_span::sym;
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits;
|
||||||
|
|
||||||
mod builtin;
|
mod builtin;
|
||||||
|
@ -39,61 +40,26 @@ fn enforce_trait_manually_implementable(
|
||||||
impl_def_id: LocalDefId,
|
impl_def_id: LocalDefId,
|
||||||
trait_def_id: DefId,
|
trait_def_id: DefId,
|
||||||
) {
|
) {
|
||||||
let did = Some(trait_def_id);
|
|
||||||
let li = tcx.lang_items();
|
|
||||||
let impl_header_span = tcx.def_span(impl_def_id);
|
let impl_header_span = tcx.def_span(impl_def_id);
|
||||||
|
|
||||||
// Disallow *all* explicit impls of `Pointee`, `DiscriminantKind`, `Sized` and `Unsize` for now.
|
// Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]`
|
||||||
if did == li.pointee_trait() {
|
if tcx.has_attr(trait_def_id, sym::rustc_deny_explicit_impl) {
|
||||||
struct_span_err!(
|
let trait_name = tcx.item_name(trait_def_id);
|
||||||
|
let mut err = struct_span_err!(
|
||||||
tcx.sess,
|
tcx.sess,
|
||||||
impl_header_span,
|
impl_header_span,
|
||||||
E0322,
|
E0322,
|
||||||
"explicit impls for the `Pointee` trait are not permitted"
|
"explicit impls for the `{trait_name}` trait are not permitted"
|
||||||
)
|
);
|
||||||
.span_label(impl_header_span, "impl of `Pointee` not allowed")
|
err.span_label(impl_header_span, format!("impl of `{trait_name}` not allowed"));
|
||||||
.emit();
|
|
||||||
return;
|
// Maintain explicit error code for `Unsize`, since it has a useful
|
||||||
|
// explanation about using `CoerceUnsized` instead.
|
||||||
|
if Some(trait_def_id) == tcx.lang_items().unsize_trait() {
|
||||||
|
err.code(error_code!(E0328));
|
||||||
}
|
}
|
||||||
|
|
||||||
if did == li.discriminant_kind_trait() {
|
err.emit();
|
||||||
struct_span_err!(
|
|
||||||
tcx.sess,
|
|
||||||
impl_header_span,
|
|
||||||
E0322,
|
|
||||||
"explicit impls for the `DiscriminantKind` trait are not permitted"
|
|
||||||
)
|
|
||||||
.span_label(impl_header_span, "impl of `DiscriminantKind` not allowed")
|
|
||||||
.emit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if did == li.sized_trait() {
|
|
||||||
struct_span_err!(
|
|
||||||
tcx.sess,
|
|
||||||
impl_header_span,
|
|
||||||
E0322,
|
|
||||||
"explicit impls for the `Sized` trait are not permitted"
|
|
||||||
)
|
|
||||||
.span_label(impl_header_span, "impl of `Sized` not allowed")
|
|
||||||
.emit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if did == li.unsize_trait() {
|
|
||||||
struct_span_err!(
|
|
||||||
tcx.sess,
|
|
||||||
impl_header_span,
|
|
||||||
E0328,
|
|
||||||
"explicit impls for the `Unsize` trait are not permitted"
|
|
||||||
)
|
|
||||||
.span_label(impl_header_span, "impl of `Unsize` not allowed")
|
|
||||||
.emit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if tcx.features().unboxed_closures {
|
|
||||||
// the feature gate allows all Fn traits
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1251,6 +1251,7 @@ symbols! {
|
||||||
rustc_deallocator,
|
rustc_deallocator,
|
||||||
rustc_def_path,
|
rustc_def_path,
|
||||||
rustc_default_body_unstable,
|
rustc_default_body_unstable,
|
||||||
|
rustc_deny_explicit_impl,
|
||||||
rustc_diagnostic_item,
|
rustc_diagnostic_item,
|
||||||
rustc_diagnostic_macros,
|
rustc_diagnostic_macros,
|
||||||
rustc_dirty,
|
rustc_dirty,
|
||||||
|
|
|
@ -96,6 +96,7 @@ unsafe impl<T: Sync + ?Sized> Send for &T {}
|
||||||
)]
|
)]
|
||||||
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
|
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
|
||||||
#[rustc_specialization_trait]
|
#[rustc_specialization_trait]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
|
||||||
pub trait Sized {
|
pub trait Sized {
|
||||||
// Empty.
|
// Empty.
|
||||||
}
|
}
|
||||||
|
@ -127,6 +128,7 @@ pub trait Sized {
|
||||||
/// [nomicon-coerce]: ../../nomicon/coercions.html
|
/// [nomicon-coerce]: ../../nomicon/coercions.html
|
||||||
#[unstable(feature = "unsize", issue = "27732")]
|
#[unstable(feature = "unsize", issue = "27732")]
|
||||||
#[lang = "unsize"]
|
#[lang = "unsize"]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
|
||||||
pub trait Unsize<T: ?Sized> {
|
pub trait Unsize<T: ?Sized> {
|
||||||
// Empty.
|
// Empty.
|
||||||
}
|
}
|
||||||
|
@ -693,6 +695,7 @@ impl<T: ?Sized> StructuralEq for PhantomData<T> {}
|
||||||
reason = "this trait is unlikely to ever be stabilized, use `mem::discriminant` instead"
|
reason = "this trait is unlikely to ever be stabilized, use `mem::discriminant` instead"
|
||||||
)]
|
)]
|
||||||
#[lang = "discriminant_kind"]
|
#[lang = "discriminant_kind"]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
|
||||||
pub trait DiscriminantKind {
|
pub trait DiscriminantKind {
|
||||||
/// The type of the discriminant, which must satisfy the trait
|
/// The type of the discriminant, which must satisfy the trait
|
||||||
/// bounds required by `mem::Discriminant`.
|
/// bounds required by `mem::Discriminant`.
|
||||||
|
@ -793,6 +796,7 @@ impl<T: ?Sized> Unpin for *mut T {}
|
||||||
#[lang = "destruct"]
|
#[lang = "destruct"]
|
||||||
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
|
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
|
||||||
pub trait Destruct {}
|
pub trait Destruct {}
|
||||||
|
|
||||||
/// A marker for tuple types.
|
/// A marker for tuple types.
|
||||||
|
@ -802,6 +806,7 @@ pub trait Destruct {}
|
||||||
#[unstable(feature = "tuple_trait", issue = "none")]
|
#[unstable(feature = "tuple_trait", issue = "none")]
|
||||||
#[lang = "tuple_trait"]
|
#[lang = "tuple_trait"]
|
||||||
#[rustc_on_unimplemented(message = "`{Self}` is not a tuple")]
|
#[rustc_on_unimplemented(message = "`{Self}` is not a tuple")]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
|
||||||
pub trait Tuple {}
|
pub trait Tuple {}
|
||||||
|
|
||||||
/// Implementations of `Copy` for primitive types.
|
/// Implementations of `Copy` for primitive types.
|
||||||
|
|
|
@ -50,6 +50,7 @@ use crate::hash::{Hash, Hasher};
|
||||||
///
|
///
|
||||||
/// [`to_raw_parts`]: *const::to_raw_parts
|
/// [`to_raw_parts`]: *const::to_raw_parts
|
||||||
#[lang = "pointee_trait"]
|
#[lang = "pointee_trait"]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
|
||||||
pub trait Pointee {
|
pub trait Pointee {
|
||||||
/// The type for metadata in pointers and references to `Self`.
|
/// The type for metadata in pointers and references to `Self`.
|
||||||
#[lang = "metadata_type"]
|
#[lang = "metadata_type"]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue