Add rustc_do_not_implement_via_object

This commit is contained in:
Michael Goulet 2023-06-02 05:54:52 +00:00
parent 5683791ebb
commit 657d3f43a9
11 changed files with 47 additions and 3 deletions

View File

@ -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 \

View File

@ -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,
}
}

View File

@ -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<Box<[Ident]>>,
/// 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

View File

@ -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,

View File

@ -631,6 +631,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>,
) {
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())

View File

@ -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<T: ?Sized> {
// Empty.
}
@ -855,6 +856,7 @@ impl<T: ?Sized> StructuralEq for PhantomData<T> {}
)]
#[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.

View File

@ -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<Src, Context, const ASSUME: Assume = { Assume::NOTHING }>
where
Src: ?Sized,

View File

@ -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"]

View File

@ -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<T: ?Sized>(&self) -> &T
| ---- required by a bound in this associated function

View File

@ -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<T: ?Sized>(&self) -> &T
| ---- required by a bound in this associated function
LL | where
LL | Self: CastTo<T>,
| ^^^^^^^^^ required by this bound in `Cast::cast`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -1,3 +1,6 @@
// revisions: current next
//[next] compile-flags: -Ztrait-solver=next
#![feature(unsize)]
use std::marker::Unsize;