Skip to content

Commit 55ff8bf

Browse files
authored
Rollup merge of #104339 - compiler-errors:rustc_deny_explicit_impl, r=cjgillot
Add `rustc_deny_explicit_impl` Also adjust `E0322` error message to be more general, since it's used for `DiscriminantKind` and `Pointee` as well. Also add `rustc_deny_explicit_impl` on the `Tuple` and `Destruct` marker traits.
2 parents a9b9215 + b5b6467 commit 55ff8bf

File tree

6 files changed

+29
-51
lines changed

6 files changed

+29
-51
lines changed

compiler/rustc_error_codes/src/error_codes/E0322.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
The `Sized` trait was implemented explicitly.
1+
A built-in trait was implemented explicitly. All implementations of the trait
2+
are provided automatically by the compiler.
23

34
Erroneous code example:
45

compiler/rustc_feature/src/builtin_attrs.rs

+4
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
691691
rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true,
692692
"#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl."
693693
),
694+
rustc_attr!(
695+
rustc_deny_explicit_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: false,
696+
"#[rustc_deny_explicit_impl] enforces that a trait can have no user-provided impls"
697+
),
694698
rustc_attr!(
695699
rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word), ErrorFollowing,
696700
"#[rustc_has_incoherent_inherent_impls] allows the addition of incoherent inherent impls for \

compiler/rustc_hir_analysis/src/coherence/mod.rs

+16-50
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
// done by the orphan and overlap modules. Then we build up various
66
// mappings. That mapping code resides here.
77

8-
use rustc_errors::struct_span_err;
8+
use rustc_errors::{error_code, struct_span_err};
99
use rustc_hir::def_id::{DefId, LocalDefId};
1010
use rustc_middle::ty::query::Providers;
1111
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
12+
use rustc_span::sym;
1213
use rustc_trait_selection::traits;
1314

1415
mod builtin;
@@ -39,61 +40,26 @@ fn enforce_trait_manually_implementable(
3940
impl_def_id: LocalDefId,
4041
trait_def_id: DefId,
4142
) {
42-
let did = Some(trait_def_id);
43-
let li = tcx.lang_items();
4443
let impl_header_span = tcx.def_span(impl_def_id);
4544

46-
// Disallow *all* explicit impls of `Pointee`, `DiscriminantKind`, `Sized` and `Unsize` for now.
47-
if did == li.pointee_trait() {
48-
struct_span_err!(
45+
// Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]`
46+
if tcx.has_attr(trait_def_id, sym::rustc_deny_explicit_impl) {
47+
let trait_name = tcx.item_name(trait_def_id);
48+
let mut err = struct_span_err!(
4949
tcx.sess,
5050
impl_header_span,
5151
E0322,
52-
"explicit impls for the `Pointee` trait are not permitted"
53-
)
54-
.span_label(impl_header_span, "impl of `Pointee` not allowed")
55-
.emit();
56-
return;
57-
}
58-
59-
if did == li.discriminant_kind_trait() {
60-
struct_span_err!(
61-
tcx.sess,
62-
impl_header_span,
63-
E0322,
64-
"explicit impls for the `DiscriminantKind` trait are not permitted"
65-
)
66-
.span_label(impl_header_span, "impl of `DiscriminantKind` not allowed")
67-
.emit();
68-
return;
69-
}
70-
71-
if did == li.sized_trait() {
72-
struct_span_err!(
73-
tcx.sess,
74-
impl_header_span,
75-
E0322,
76-
"explicit impls for the `Sized` trait are not permitted"
77-
)
78-
.span_label(impl_header_span, "impl of `Sized` not allowed")
79-
.emit();
80-
return;
81-
}
82-
83-
if did == li.unsize_trait() {
84-
struct_span_err!(
85-
tcx.sess,
86-
impl_header_span,
87-
E0328,
88-
"explicit impls for the `Unsize` trait are not permitted"
89-
)
90-
.span_label(impl_header_span, "impl of `Unsize` not allowed")
91-
.emit();
92-
return;
93-
}
52+
"explicit impls for the `{trait_name}` trait are not permitted"
53+
);
54+
err.span_label(impl_header_span, format!("impl of `{trait_name}` not allowed"));
55+
56+
// Maintain explicit error code for `Unsize`, since it has a useful
57+
// explanation about using `CoerceUnsized` instead.
58+
if Some(trait_def_id) == tcx.lang_items().unsize_trait() {
59+
err.code(error_code!(E0328));
60+
}
9461

95-
if tcx.features().unboxed_closures {
96-
// the feature gate allows all Fn traits
62+
err.emit();
9763
return;
9864
}
9965

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,7 @@ symbols! {
12101210
rustc_deallocator,
12111211
rustc_def_path,
12121212
rustc_default_body_unstable,
1213+
rustc_deny_explicit_impl,
12131214
rustc_diagnostic_item,
12141215
rustc_diagnostic_macros,
12151216
rustc_dirty,

library/core/src/marker.rs

+5
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ unsafe impl<T: Sync + ?Sized> Send for &T {}
9696
)]
9797
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
9898
#[rustc_specialization_trait]
99+
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
99100
pub trait Sized {
100101
// Empty.
101102
}
@@ -127,6 +128,7 @@ pub trait Sized {
127128
/// [nomicon-coerce]: ../../nomicon/coercions.html
128129
#[unstable(feature = "unsize", issue = "27732")]
129130
#[lang = "unsize"]
131+
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
130132
pub trait Unsize<T: ?Sized> {
131133
// Empty.
132134
}
@@ -693,6 +695,7 @@ impl<T: ?Sized> StructuralEq for PhantomData<T> {}
693695
reason = "this trait is unlikely to ever be stabilized, use `mem::discriminant` instead"
694696
)]
695697
#[lang = "discriminant_kind"]
698+
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
696699
pub trait DiscriminantKind {
697700
/// The type of the discriminant, which must satisfy the trait
698701
/// bounds required by `mem::Discriminant`.
@@ -793,6 +796,7 @@ impl<T: ?Sized> Unpin for *mut T {}
793796
#[lang = "destruct"]
794797
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
795798
#[const_trait]
799+
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
796800
pub trait Destruct {}
797801

798802
/// A marker for tuple types.
@@ -802,6 +806,7 @@ pub trait Destruct {}
802806
#[unstable(feature = "tuple_trait", issue = "none")]
803807
#[lang = "tuple_trait"]
804808
#[rustc_on_unimplemented(message = "`{Self}` is not a tuple")]
809+
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
805810
pub trait Tuple {}
806811

807812
/// Implementations of `Copy` for primitive types.

library/core/src/ptr/metadata.rs

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ use crate::hash::{Hash, Hasher};
5050
///
5151
/// [`to_raw_parts`]: *const::to_raw_parts
5252
#[lang = "pointee_trait"]
53+
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)]
5354
pub trait Pointee {
5455
/// The type for metadata in pointers and references to `Self`.
5556
#[lang = "metadata_type"]

0 commit comments

Comments
 (0)