Skip to content

Commit

Permalink
Add rustc_do_not_implement_via_object
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Jun 20, 2023
1 parent 5683791 commit 657d3f4
Show file tree
Hide file tree
Showing 11 changed files with 47 additions and 3 deletions.
5 changes: 5 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand All @@ -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,
}
}

Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_middle/src/ty/trait_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_trait_selection/src/solve/assembly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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())
Expand Down
4 changes: 4 additions & 0 deletions library/core/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
}
Expand Down Expand Up @@ -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`.
Expand Down Expand Up @@ -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 {}

Expand All @@ -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.
Expand Down
1 change: 1 addition & 0 deletions library/core/src/mem/transmutability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions library/core/src/ptr/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
18 changes: 18 additions & 0 deletions tests/ui/unsized/issue-71659.next.stderr
Original file line number Diff line number Diff line change
@@ -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`.
3 changes: 3 additions & 0 deletions tests/ui/unsized/issue-71659.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// revisions: current next
//[next] compile-flags: -Ztrait-solver=next

#![feature(unsize)]

use std::marker::Unsize;
Expand Down

0 comments on commit 657d3f4

Please sign in to comment.