diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 9be28c338f6..566f856258a 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -708,6 +708,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ 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_do_not_implement_via_object, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true, + "#[rustc_do_not_implement_via_object] marks a trait so that `dyn Trait` does not \ + implement `Trait` (without requiring `Sized` as a supertrait)" + ), rustc_attr!( rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word), ErrorFollowing, "#[rustc_has_incoherent_inherent_impls] allows the addition of incoherent inherent impls for \ diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index c7b9fc9a697..96cbe975f36 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -985,6 +985,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { no_dups.then_some(list) }); + let do_not_implement_via_object = tcx.has_attr(def_id, sym::rustc_do_not_implement_via_object); ty::TraitDef { def_id: def_id.to_def_id(), @@ -996,6 +997,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { skip_array_during_method_dispatch, specialization_kind, must_implement_one_of, + do_not_implement_via_object, } } diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index e61037e5ea8..14352307094 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -52,6 +52,11 @@ pub struct TraitDef { /// List of functions from `#[rustc_must_implement_one_of]` attribute one of which /// must be implemented. pub must_implement_one_of: Option>, + + /// Whether a type's built-in `dyn Trait: Trait` implementation is explicitly + /// denied. This only applies to built-in trait, and is marked via + /// `#[rustc_do_not_implement_via_object]`. + pub do_not_implement_via_object: bool, } /// Whether this trait is treated specially by the standard library diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c5ce2575fff..f476f891631 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1270,6 +1270,7 @@ symbols! { rustc_diagnostic_macros, rustc_dirty, rustc_do_not_const_check, + rustc_do_not_implement_via_object, rustc_doc_primitive, rustc_dummy, rustc_dump_env_program_clauses, diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 1b749b9c854..ab8dd854fa4 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -631,6 +631,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, G>, candidates: &mut Vec>, ) { + let tcx = self.tcx(); + if !tcx.trait_def(goal.predicate.trait_def_id(tcx)).implement_via_object { + return; + } + let self_ty = goal.predicate.self_ty(); let bounds = match *self_ty.kind() { ty::Bool @@ -663,7 +668,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ty::Dynamic(bounds, ..) => bounds, }; - let tcx = self.tcx(); let own_bounds: FxIndexSet<_> = bounds.iter().map(|bound| bound.with_self_ty(tcx, self_ty)).collect(); for assumption in elaborate(tcx, own_bounds.iter().copied()) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 9a541ccaeac..e1359aa09a2 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -174,6 +174,7 @@ pub trait Sized { #[unstable(feature = "unsize", issue = "18598")] #[lang = "unsize"] #[rustc_deny_explicit_impl] +#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] pub trait Unsize { // Empty. } @@ -855,6 +856,7 @@ impl StructuralEq for PhantomData {} )] #[lang = "discriminant_kind"] #[rustc_deny_explicit_impl] +#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] pub trait DiscriminantKind { /// The type of the discriminant, which must satisfy the trait /// bounds required by `mem::Discriminant`. @@ -960,6 +962,7 @@ marker_impls! { #[lang = "destruct"] #[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)] #[rustc_deny_explicit_impl] +#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] #[const_trait] pub trait Destruct {} @@ -971,6 +974,7 @@ pub trait Destruct {} #[lang = "tuple_trait"] #[rustc_on_unimplemented(message = "`{Self}` is not a tuple")] #[rustc_deny_explicit_impl] +#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] pub trait Tuple {} /// A marker for pointer-like types. diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs index a6f792ed0e3..8ba4313cc1e 100644 --- a/library/core/src/mem/transmutability.rs +++ b/library/core/src/mem/transmutability.rs @@ -7,6 +7,7 @@ use crate::marker::ConstParamTy; /// notwithstanding whatever safety checks you have asked the compiler to [`Assume`] are satisfied. #[unstable(feature = "transmutability", issue = "99571")] #[lang = "transmute_trait"] +#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] pub unsafe trait BikeshedIntrinsicFrom where Src: ?Sized, diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 2ea032d4aff..34f31fb9fc6 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -51,6 +51,7 @@ use crate::hash::{Hash, Hasher}; /// [`to_raw_parts`]: *const::to_raw_parts #[lang = "pointee_trait"] #[rustc_deny_explicit_impl] +#[cfg_attr(not(bootstrap), rustc_do_not_implement_via_object)] pub trait Pointee { /// The type for metadata in pointers and references to `Self`. #[lang = "metadata_type"] diff --git a/tests/ui/unsized/issue-71659.stderr b/tests/ui/unsized/issue-71659.current.stderr similarity index 89% rename from tests/ui/unsized/issue-71659.stderr rename to tests/ui/unsized/issue-71659.current.stderr index b57b3015e47..6b982a73952 100644 --- a/tests/ui/unsized/issue-71659.stderr +++ b/tests/ui/unsized/issue-71659.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied - --> $DIR/issue-71659.rs:30:15 + --> $DIR/issue-71659.rs:33:15 | LL | let x = x.cast::<[i32]>(); | ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo` | note: required by a bound in `Cast::cast` - --> $DIR/issue-71659.rs:19:15 + --> $DIR/issue-71659.rs:22:15 | LL | fn cast(&self) -> &T | ---- required by a bound in this associated function diff --git a/tests/ui/unsized/issue-71659.next.stderr b/tests/ui/unsized/issue-71659.next.stderr new file mode 100644 index 00000000000..6b982a73952 --- /dev/null +++ b/tests/ui/unsized/issue-71659.next.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied + --> $DIR/issue-71659.rs:33:15 + | +LL | let x = x.cast::<[i32]>(); + | ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo` + | +note: required by a bound in `Cast::cast` + --> $DIR/issue-71659.rs:22:15 + | +LL | fn cast(&self) -> &T + | ---- required by a bound in this associated function +LL | where +LL | Self: CastTo, + | ^^^^^^^^^ required by this bound in `Cast::cast` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized/issue-71659.rs b/tests/ui/unsized/issue-71659.rs index 3524ca02bbf..db5c2e205aa 100644 --- a/tests/ui/unsized/issue-71659.rs +++ b/tests/ui/unsized/issue-71659.rs @@ -1,3 +1,6 @@ +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next + #![feature(unsize)] use std::marker::Unsize;