Skip to content

Commit ca68cf0

Browse files
Merge attrs, better validation
1 parent 91e5c3f commit ca68cf0

File tree

16 files changed

+140
-73
lines changed

16 files changed

+140
-73
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -705,14 +705,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
705705
"#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl."
706706
),
707707
rustc_attr!(
708-
rustc_deny_explicit_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true,
708+
rustc_deny_explicit_impl,
709+
AttributeType::Normal,
710+
template!(List: "implement_via_object = (true|false)"),
711+
ErrorFollowing,
712+
@only_local: true,
709713
"#[rustc_deny_explicit_impl] enforces that a trait can have no user-provided impls"
710714
),
711-
rustc_attr!(
712-
rustc_do_not_implement_via_object, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true,
713-
"#[rustc_do_not_implement_via_object] marks a trait so that `dyn Trait` does not \
714-
implement `Trait` (without requiring `Sized` as a supertrait)"
715-
),
716715
rustc_attr!(
717716
rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word), ErrorFollowing,
718717
"#[rustc_has_incoherent_inherent_impls] allows the addition of incoherent inherent impls for \

compiler/rustc_hir_analysis/src/collect.rs

+44-2
Original file line numberDiff line numberDiff line change
@@ -985,8 +985,50 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
985985

986986
no_dups.then_some(list)
987987
});
988-
let do_not_implement_via_object = tcx.has_attr(def_id, sym::rustc_do_not_implement_via_object);
989-
let deny_explicit_impl = tcx.has_attr(def_id, sym::rustc_deny_explicit_impl);
988+
989+
let mut deny_explicit_impl = false;
990+
let mut implement_via_object = true;
991+
if let Some(attr) = tcx.get_attr(def_id, sym::rustc_deny_explicit_impl) {
992+
deny_explicit_impl = true;
993+
let mut seen_attr = false;
994+
for meta in attr.meta_item_list().iter().flatten() {
995+
if let Some(meta) = meta.meta_item()
996+
&& meta.name_or_empty() == sym::implement_via_object
997+
&& let Some(lit) = meta.name_value_literal()
998+
{
999+
if seen_attr {
1000+
tcx.sess.span_err(
1001+
meta.span,
1002+
"duplicated `implement_via_object` meta item",
1003+
);
1004+
}
1005+
seen_attr = true;
1006+
1007+
match lit.symbol {
1008+
kw::True => {
1009+
implement_via_object = true;
1010+
}
1011+
kw::False => {
1012+
implement_via_object = false;
1013+
}
1014+
_ => {
1015+
tcx.sess.span_err(
1016+
meta.span,
1017+
format!("unknown literal passed to `implement_via_object` attribute: {}", lit.symbol),
1018+
);
1019+
}
1020+
}
1021+
} else {
1022+
tcx.sess.span_err(
1023+
meta.span(),
1024+
format!("unknown meta item passed to `rustc_deny_explicit_impl` {:?}", meta),
1025+
);
1026+
}
1027+
}
1028+
if !seen_attr {
1029+
tcx.sess.span_err(attr.span, "missing `implement_via_object` meta item");
1030+
}
1031+
}
9901032

9911033
ty::TraitDef {
9921034
def_id: def_id.to_def_id(),

compiler/rustc_middle/src/ty/trait_def.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,14 @@ pub struct TraitDef {
5353
/// must be implemented.
5454
pub must_implement_one_of: Option<Box<[Ident]>>,
5555

56-
/// Whether a type's built-in `dyn Trait: Trait` implementation is explicitly
57-
/// denied. This only applies to built-in trait, and is marked via
58-
/// `#[rustc_do_not_implement_via_object]`.
59-
pub do_not_implement_via_object: bool,
56+
/// Whether to add a builtin `dyn Trait: Trait` implementation.
57+
/// This is enabled for all traits except ones marked with
58+
/// `#[rustc_deny_explicit_impl(implement_via_object = false)]`.
59+
pub implement_via_object: bool,
6060

6161
/// Whether a trait is fully built-in, and any implementation is disallowed.
62+
/// This only applies to built-in traits, and is marked via
63+
/// `#[rustc_deny_explicit_impl(implement_via_object = ...)]`.
6264
pub deny_explicit_impl: bool,
6365
}
6466

compiler/rustc_passes/messages.ftl

-3
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,6 @@ passes_const_impl_const_trait =
102102
const `impl`s must be for traits marked with `#[const_trait]`
103103
.note = this trait must be annotated with `#[const_trait]`
104104
105-
passes_const_trait =
106-
attribute should be applied to a trait
107-
108105
passes_continue_labeled_block =
109106
`continue` pointing to a labeled block
110107
.label = labeled blocks cannot be `continue`'d

compiler/rustc_passes/src/check_attr.rs

+6-37
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,6 @@ impl CheckAttrVisitor<'_> {
110110
sym::no_coverage => self.check_no_coverage(hir_id, attr, span, target),
111111
sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target),
112112
sym::marker => self.check_marker(hir_id, attr, span, target),
113-
sym::rustc_must_implement_one_of => {
114-
self.check_rustc_must_implement_one_of(attr, span, target)
115-
}
116113
sym::target_feature => self.check_target_feature(hir_id, attr, span, target),
117114
sym::thread_local => self.check_thread_local(attr, span, target),
118115
sym::track_caller => {
@@ -159,12 +156,14 @@ impl CheckAttrVisitor<'_> {
159156
| sym::rustc_dirty
160157
| sym::rustc_if_this_changed
161158
| sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr),
162-
sym::rustc_coinductive => self.check_rustc_coinductive(&attr, span, target),
159+
sym::rustc_coinductive
160+
| sym::rustc_must_implement_one_of
161+
| sym::rustc_deny_explicit_impl
162+
| sym::const_trait => self.check_must_be_applied_to_trait(&attr, span, target),
163163
sym::cmse_nonsecure_entry => {
164164
self.check_cmse_nonsecure_entry(hir_id, attr, span, target)
165165
}
166166
sym::collapse_debuginfo => self.check_collapse_debuginfo(attr, span, target),
167-
sym::const_trait => self.check_const_trait(attr, span, target),
168167
sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
169168
sym::must_use => self.check_must_use(hir_id, &attr, target),
170169
sym::rustc_pass_by_value => self.check_pass_by_value(&attr, span, target),
@@ -567,25 +566,6 @@ impl CheckAttrVisitor<'_> {
567566
}
568567
}
569568

570-
/// Checks if the `#[rustc_must_implement_one_of]` attribute on a `target` is valid. Returns `true` if valid.
571-
fn check_rustc_must_implement_one_of(
572-
&self,
573-
attr: &Attribute,
574-
span: Span,
575-
target: Target,
576-
) -> bool {
577-
match target {
578-
Target::Trait => true,
579-
_ => {
580-
self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToTrait {
581-
attr_span: attr.span,
582-
defn_span: span,
583-
});
584-
false
585-
}
586-
}
587-
}
588-
589569
/// Checks if the `#[target_feature]` attribute on `item` is valid. Returns `true` if valid.
590570
fn check_target_feature(
591571
&self,
@@ -1591,8 +1571,8 @@ impl CheckAttrVisitor<'_> {
15911571
}
15921572
}
15931573

1594-
/// Checks if the `#[rustc_coinductive]` attribute is applied to a trait.
1595-
fn check_rustc_coinductive(&self, attr: &Attribute, span: Span, target: Target) -> bool {
1574+
/// Checks if the attribute is applied to a trait.
1575+
fn check_must_be_applied_to_trait(&self, attr: &Attribute, span: Span, target: Target) -> bool {
15961576
match target {
15971577
Target::Trait => true,
15981578
_ => {
@@ -1986,17 +1966,6 @@ impl CheckAttrVisitor<'_> {
19861966
}
19871967
}
19881968

1989-
/// `#[const_trait]` only applies to traits.
1990-
fn check_const_trait(&self, attr: &Attribute, _span: Span, target: Target) -> bool {
1991-
match target {
1992-
Target::Trait => true,
1993-
_ => {
1994-
self.tcx.sess.emit_err(errors::ConstTrait { attr_span: attr.span });
1995-
false
1996-
}
1997-
}
1998-
}
1999-
20001969
fn check_stability_promotable(&self, attr: &Attribute, _span: Span, target: Target) -> bool {
20011970
match target {
20021971
Target::Expression => {

compiler/rustc_passes/src/errors.rs

-7
Original file line numberDiff line numberDiff line change
@@ -610,13 +610,6 @@ pub struct RustcStdInternalSymbol {
610610
pub span: Span,
611611
}
612612

613-
#[derive(Diagnostic)]
614-
#[diag(passes_const_trait)]
615-
pub struct ConstTrait {
616-
#[primary_span]
617-
pub attr_span: Span,
618-
}
619-
620613
#[derive(Diagnostic)]
621614
#[diag(passes_link_ordinal)]
622615
pub struct LinkOrdinal {

compiler/rustc_span/src/symbol.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,7 @@ symbols! {
817817
impl_trait_in_bindings,
818818
impl_trait_in_fn_trait_return,
819819
impl_trait_projections,
820+
implement_via_object,
820821
implied_by,
821822
import,
822823
import_name_type,
@@ -1270,7 +1271,6 @@ symbols! {
12701271
rustc_diagnostic_macros,
12711272
rustc_dirty,
12721273
rustc_do_not_const_check,
1273-
rustc_do_not_implement_via_object,
12741274
rustc_doc_primitive,
12751275
rustc_dummy,
12761276
rustc_dump_env_program_clauses,

compiler/rustc_trait_selection/src/traits/project.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1586,6 +1586,10 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
15861586

15871587
let tcx = selcx.tcx();
15881588

1589+
if !tcx.trait_def(obligation.predicate.trait_def_id(tcx)).implement_via_object {
1590+
return;
1591+
}
1592+
15891593
let self_ty = obligation.predicate.self_ty();
15901594
let object_ty = selcx.infcx.shallow_resolve(self_ty);
15911595
let data = match object_ty.kind() {

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+4
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
554554
"assemble_candidates_from_object_ty",
555555
);
556556

557+
if !self.tcx().trait_def(obligation.predicate.def_id()).implement_via_object {
558+
return;
559+
}
560+
557561
self.infcx.probe(|_snapshot| {
558562
if obligation.has_non_region_late_bound() {
559563
return;

library/core/src/marker.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ unsafe impl<T: Sync + ?Sized> Send for &T {}
140140
)]
141141
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
142142
#[rustc_specialization_trait]
143-
#[rustc_deny_explicit_impl]
143+
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl(implement_via_object = false))]
144+
#[cfg_attr(bootstrap, rustc_deny_explicit_impl)]
144145
#[rustc_coinductive]
145146
pub trait Sized {
146147
// Empty.
@@ -173,8 +174,8 @@ pub trait Sized {
173174
/// [nomicon-coerce]: ../../nomicon/coercions.html
174175
#[unstable(feature = "unsize", issue = "18598")]
175176
#[lang = "unsize"]
176-
#[rustc_deny_explicit_impl]
177-
#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)]
177+
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl(implement_via_object = false))]
178+
#[cfg_attr(bootstrap, rustc_deny_explicit_impl)]
178179
pub trait Unsize<T: ?Sized> {
179180
// Empty.
180181
}
@@ -855,8 +856,8 @@ impl<T: ?Sized> StructuralEq for PhantomData<T> {}
855856
reason = "this trait is unlikely to ever be stabilized, use `mem::discriminant` instead"
856857
)]
857858
#[lang = "discriminant_kind"]
858-
#[rustc_deny_explicit_impl]
859-
#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)]
859+
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl(implement_via_object = false))]
860+
#[cfg_attr(bootstrap, rustc_deny_explicit_impl)]
860861
pub trait DiscriminantKind {
861862
/// The type of the discriminant, which must satisfy the trait
862863
/// bounds required by `mem::Discriminant`.
@@ -961,8 +962,8 @@ marker_impls! {
961962
#[unstable(feature = "const_trait_impl", issue = "67792")]
962963
#[lang = "destruct"]
963964
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
964-
#[rustc_deny_explicit_impl]
965-
#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)]
965+
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl(implement_via_object = false))]
966+
#[cfg_attr(bootstrap, rustc_deny_explicit_impl)]
966967
#[const_trait]
967968
pub trait Destruct {}
968969

@@ -973,8 +974,8 @@ pub trait Destruct {}
973974
#[unstable(feature = "tuple_trait", issue = "none")]
974975
#[lang = "tuple_trait"]
975976
#[rustc_on_unimplemented(message = "`{Self}` is not a tuple")]
976-
#[rustc_deny_explicit_impl]
977-
#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)]
977+
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl(implement_via_object = false))]
978+
#[cfg_attr(bootstrap, rustc_deny_explicit_impl)]
978979
pub trait Tuple {}
979980

980981
/// A marker for pointer-like types.
@@ -1029,7 +1030,8 @@ impl ConstParamTy for () {}
10291030
reason = "internal trait for implementing various traits for all function pointers"
10301031
)]
10311032
#[lang = "fn_ptr_trait"]
1032-
#[rustc_deny_explicit_impl]
1033+
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl(implement_via_object = false))]
1034+
#[cfg_attr(bootstrap, rustc_deny_explicit_impl)]
10331035
pub trait FnPtr: Copy + Clone {
10341036
/// Returns the address of the function pointer.
10351037
#[lang = "fn_ptr_addr"]

library/core/src/mem/transmutability.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use crate::marker::ConstParamTy;
77
/// notwithstanding whatever safety checks you have asked the compiler to [`Assume`] are satisfied.
88
#[unstable(feature = "transmutability", issue = "99571")]
99
#[lang = "transmute_trait"]
10-
#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)]
10+
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl(implement_via_object = false))]
11+
#[cfg_attr(bootstrap, rustc_deny_explicit_impl)]
1112
pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }>
1213
where
1314
Src: ?Sized,

library/core/src/ptr/metadata.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ use crate::hash::{Hash, Hasher};
5050
///
5151
/// [`to_raw_parts`]: *const::to_raw_parts
5252
#[lang = "pointee_trait"]
53-
#[rustc_deny_explicit_impl]
54-
#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)]
53+
#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl(implement_via_object = false))]
54+
#[cfg_attr(bootstrap, rustc_deny_explicit_impl)]
5555
pub trait Pointee {
5656
/// The type for metadata in pointers and references to `Self`.
5757
#[lang = "metadata_type"]

tests/ui/rfcs/rfc-2632-const-trait-impl/attr-misuse.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ error: attribute should be applied to a trait
33
|
44
LL | #[const_trait]
55
| ^^^^^^^^^^^^^^
6+
LL | fn main() {}
7+
| ------------ not a trait
68

79
error: attribute should be applied to a trait
810
--> $DIR/attr-misuse.rs:5:5
911
|
1012
LL | #[const_trait]
1113
| ^^^^^^^^^^^^^^
14+
LL | fn foo(self);
15+
| ------------- not a trait
1216

1317
error: aborting due to 2 previous errors
1418

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0277]: the trait bound `dyn NotObject: NotObject` is not satisfied
2+
--> $DIR/deny-builtin-object-impl.rs:18:23
3+
|
4+
LL | test_not_object::<dyn NotObject>();
5+
| ^^^^^^^^^^^^^ the trait `NotObject` is not implemented for `dyn NotObject`
6+
|
7+
note: required by a bound in `test_not_object`
8+
--> $DIR/deny-builtin-object-impl.rs:14:23
9+
|
10+
LL | fn test_not_object<T: NotObject + ?Sized>() {}
11+
| ^^^^^^^^^ required by this bound in `test_not_object`
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0277]: the trait bound `dyn NotObject: NotObject` is not satisfied
2+
--> $DIR/deny-builtin-object-impl.rs:18:23
3+
|
4+
LL | test_not_object::<dyn NotObject>();
5+
| ^^^^^^^^^^^^^ the trait `NotObject` is not implemented for `dyn NotObject`
6+
|
7+
note: required by a bound in `test_not_object`
8+
--> $DIR/deny-builtin-object-impl.rs:14:23
9+
|
10+
LL | fn test_not_object<T: NotObject + ?Sized>() {}
11+
| ^^^^^^^^^ required by this bound in `test_not_object`
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// revisions: current next
2+
//[next] compile-flags: -Ztrait-solver=next
3+
4+
#![feature(rustc_attrs)]
5+
6+
#[rustc_deny_explicit_impl(implement_via_object = true)]
7+
trait YesObject {}
8+
9+
#[rustc_deny_explicit_impl(implement_via_object = false)]
10+
trait NotObject {}
11+
12+
fn test_yes_object<T: YesObject + ?Sized>() {}
13+
14+
fn test_not_object<T: NotObject + ?Sized>() {}
15+
16+
fn main() {
17+
test_yes_object::<dyn YesObject>();
18+
test_not_object::<dyn NotObject>();
19+
//~^ ERROR the trait bound `dyn NotObject: NotObject` is not satisfied
20+
}

0 commit comments

Comments
 (0)