Replace #[rustc_do_not_implement_via_object] with #[rustc_dyn_incompatible_trait], which makes the marked trait dyn-incompatible.

Removes the attribute from `MetaSized` and `PointeeSized`, with a special case in the trait solvers for `MetaSized`.

`dyn MetaSized` is a perfectly cromulent type, and seems to only have had #[rustc_do_not_implement_via_object] so the builtin object
candidate does not overlap with the builtin MetaSized impl that all `dyn` types get.
Resolves this with a special case by checking `is_sizedness_trait` where the trait solvers previously checked `implement_via_object`.

`dyn PointeeSized` alone is rejected for other reasons (since `dyn PointeeSized` is considered to have no principal trait because `PointeeSized`
is removed at an earlier stage of the compiler), but `(dyn PointeeSized + Send)` is valid and equivalent to `dyn Send`.

Add suggestions from code review

Update compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs and tests

Co-authored-by: lcnr <rust@lcnr.de>
This commit is contained in:
Zachary S 2025-11-07 00:22:14 -06:00
parent 5c49c4f7c8
commit c3205f98dd
35 changed files with 387 additions and 154 deletions

View file

@ -94,12 +94,12 @@ impl<S: Stage> NoArgsAttributeParser<S> for DenyExplicitImplParser {
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DenyExplicitImpl;
}
pub(crate) struct DoNotImplementViaObjectParser;
impl<S: Stage> NoArgsAttributeParser<S> for DoNotImplementViaObjectParser {
const PATH: &[Symbol] = &[sym::rustc_do_not_implement_via_object];
pub(crate) struct DynIncompatibleTraitParser;
impl<S: Stage> NoArgsAttributeParser<S> for DynIncompatibleTraitParser {
const PATH: &[Symbol] = &[sym::rustc_dyn_incompatible_trait];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DoNotImplementViaObject;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DynIncompatibleTrait;
}
// Specialization

View file

@ -88,8 +88,8 @@ use crate::attributes::stability::{
use crate::attributes::test_attrs::{IgnoreParser, ShouldPanicParser};
use crate::attributes::traits::{
AllowIncoherentImplParser, CoinductiveParser, DenyExplicitImplParser,
DoNotImplementViaObjectParser, FundamentalParser, MarkerParser, ParenSugarParser,
PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser,
DynIncompatibleTraitParser, FundamentalParser, MarkerParser, ParenSugarParser, PointeeParser,
SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser,
UnsafeSpecializationMarkerParser,
};
use crate::attributes::transparency::TransparencyParser;
@ -254,7 +254,7 @@ attribute_parsers!(
Single<WithoutArgs<ConstStabilityIndirectParser>>,
Single<WithoutArgs<CoroutineParser>>,
Single<WithoutArgs<DenyExplicitImplParser>>,
Single<WithoutArgs<DoNotImplementViaObjectParser>>,
Single<WithoutArgs<DynIncompatibleTraitParser>>,
Single<WithoutArgs<EiiForeignItemParser>>,
Single<WithoutArgs<ExportStableParser>>,
Single<WithoutArgs<FfiConstParser>>,

View file

@ -1315,13 +1315,13 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
"`#[rustc_deny_explicit_impl]` enforces that a trait can have no user-provided impls"
),
rustc_attr!(
rustc_do_not_implement_via_object,
rustc_dyn_incompatible_trait,
AttributeType::Normal,
template!(Word),
ErrorFollowing,
EncodeCrossCrate::No,
"`#[rustc_do_not_implement_via_object]` opts out of the automatic trait impl for trait objects \
(`impl Trait for dyn Trait`)"
"`#[rustc_dyn_incompatible_trait]` marks a trait as dyn-incompatible, \
even if it otherwise satisfies the requirements to be dyn-compatible."
),
rustc_attr!(
rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word),

View file

@ -728,9 +728,6 @@ pub enum AttributeKind {
/// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
Deprecation { deprecation: Deprecation, span: Span },
/// Represents `#[rustc_do_not_implement_via_object]`.
DoNotImplementViaObject(Span),
/// Represents `#[diagnostic::do_not_recommend]`.
DoNotRecommend { attr_span: Span },
@ -746,6 +743,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_dummy]`.
Dummy,
/// Represents `#[rustc_dyn_incompatible_trait]`.
DynIncompatibleTrait(Span),
/// Implementation detail of `#[eii]`
EiiDeclaration(EiiDecl),

View file

@ -43,11 +43,11 @@ impl AttributeKind {
DebuggerVisualizer(..) => No,
DenyExplicitImpl(..) => No,
Deprecation { .. } => Yes,
DoNotImplementViaObject(..) => No,
DoNotRecommend { .. } => Yes,
Doc(_) => Yes,
DocComment { .. } => Yes,
Dummy => No,
DynIncompatibleTrait(..) => No,
EiiDeclaration(_) => Yes,
EiiForeignItem => No,
EiiImpls(..) => No,

View file

@ -211,9 +211,7 @@ fn check_object_overlap<'tcx>(
// This is a WF error tested by `coherence-impl-trait-for-trait-dyn-compatible.rs`.
} else {
let mut supertrait_def_ids = elaborate::supertrait_def_ids(tcx, component_def_id);
if supertrait_def_ids
.any(|d| d == trait_def_id && tcx.trait_def(d).implement_via_object)
{
if supertrait_def_ids.any(|d| d == trait_def_id) {
let span = tcx.def_span(impl_def_id);
return Err(struct_span_code_err!(
tcx.dcx(),

View file

@ -924,7 +924,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
);
let deny_explicit_impl = find_attr!(attrs, AttributeKind::DenyExplicitImpl(_));
let implement_via_object = !find_attr!(attrs, AttributeKind::DoNotImplementViaObject(_));
let force_dyn_incompatible =
find_attr!(attrs, AttributeKind::DynIncompatibleTrait(span) => *span);
ty::TraitDef {
def_id: def_id.to_def_id(),
@ -939,7 +940,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
skip_boxed_slice_during_method_dispatch,
specialization_kind,
must_implement_one_of,
implement_via_object,
force_dyn_incompatible,
deny_explicit_impl,
}
}

View file

@ -764,6 +764,9 @@ pub enum DynCompatibilityViolation {
/// `Self: Sized` declared on the trait.
SizedSelf(SmallVec<[Span; 1]>),
/// Trait is marked `#[rustc_dyn_incompatible_trait]`.
ExplicitlyDynIncompatible(SmallVec<[Span; 1]>),
/// Supertrait reference references `Self` an in illegal location
/// (e.g., `trait Foo : Bar<Self>`).
SupertraitSelf(SmallVec<[Span; 1]>),
@ -788,6 +791,9 @@ impl DynCompatibilityViolation {
pub fn error_msg(&self) -> Cow<'static, str> {
match self {
DynCompatibilityViolation::SizedSelf(_) => "it requires `Self: Sized`".into(),
DynCompatibilityViolation::ExplicitlyDynIncompatible(_) => {
"it opted out of dyn-compatibility".into()
}
DynCompatibilityViolation::SupertraitSelf(spans) => {
if spans.iter().any(|sp| *sp != DUMMY_SP) {
"it uses `Self` as a type parameter".into()
@ -861,6 +867,7 @@ impl DynCompatibilityViolation {
pub fn solution(&self) -> DynCompatibilityViolationSolution {
match self {
DynCompatibilityViolation::SizedSelf(_)
| DynCompatibilityViolation::ExplicitlyDynIncompatible(_)
| DynCompatibilityViolation::SupertraitSelf(_)
| DynCompatibilityViolation::SupertraitNonLifetimeBinder(..)
| DynCompatibilityViolation::SupertraitConst(_) => {
@ -894,6 +901,7 @@ impl DynCompatibilityViolation {
match self {
DynCompatibilityViolation::SupertraitSelf(spans)
| DynCompatibilityViolation::SizedSelf(spans)
| DynCompatibilityViolation::ExplicitlyDynIncompatible(spans)
| DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans)
| DynCompatibilityViolation::SupertraitConst(spans) => spans.clone(),
DynCompatibilityViolation::AssocConst(_, span)

View file

@ -709,10 +709,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
self.trait_def(def_id).is_fundamental
}
fn trait_may_be_implemented_via_object(self, trait_def_id: DefId) -> bool {
self.trait_def(trait_def_id).implement_via_object
}
fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool {
self.trait_def(trait_def_id).safety.is_unsafe()
}

View file

@ -7,6 +7,7 @@ use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::{self as hir, find_attr};
use rustc_macros::{Decodable, Encodable, HashStable};
use rustc_span::Span;
use tracing::debug;
use crate::query::LocalCrate;
@ -69,10 +70,9 @@ pub struct TraitDef {
/// must be implemented.
pub must_implement_one_of: Option<Box<[Ident]>>,
/// Whether to add a builtin `dyn Trait: Trait` implementation.
/// This is enabled for all traits except ones marked with
/// `#[rustc_do_not_implement_via_object]`.
pub implement_via_object: bool,
/// Whether the trait should be considered dyn-incompatible, even if it otherwise
/// satisfies the requirements to be dyn-compatible.
pub force_dyn_incompatible: Option<Span>,
/// Whether a trait is fully built-in, and any implementation is disallowed.
/// This only applies to built-in traits, and is marked via

View file

@ -792,7 +792,9 @@ where
candidates: &mut Vec<Candidate<I>>,
) {
let cx = self.cx();
if !cx.trait_may_be_implemented_via_object(goal.predicate.trait_def_id(cx)) {
if cx.is_sizedness_trait(goal.predicate.trait_def_id(cx)) {
// `dyn MetaSized` is valid, but should get its `MetaSized` impl from
// being `dyn` (SizedCandidate), not from the object candidate.
return;
}

View file

@ -244,7 +244,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::SkipDuringMethodDispatch { .. }
| AttributeKind::Coinductive(..)
| AttributeKind::DenyExplicitImpl(..)
| AttributeKind::DoNotImplementViaObject(..)
| AttributeKind::DynIncompatibleTrait(..)
| AttributeKind::SpecializationTrait(..)
| AttributeKind::UnsafeSpecializationMarker(..)
| AttributeKind::ParenSugar(..)

View file

@ -1395,7 +1395,7 @@ pub struct TraitDecl {
pub skip_boxed_slice_during_method_dispatch: bool,
pub specialization_kind: TraitSpecializationKind,
pub must_implement_one_of: Option<Vec<Ident>>,
pub implement_via_object: bool,
pub force_dyn_incompatible: Option<Span>,
pub deny_explicit_impl: bool,
}

View file

@ -597,7 +597,7 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef {
.must_implement_one_of
.as_ref()
.map(|idents| idents.iter().map(|ident| opaque(ident)).collect()),
implement_via_object: self.implement_via_object,
force_dyn_incompatible: self.force_dyn_incompatible.stable(tables, cx),
deny_explicit_impl: self.deny_explicit_impl,
}
}

View file

@ -1950,7 +1950,6 @@ symbols! {
rustc_diagnostic_macros,
rustc_dirty,
rustc_do_not_const_check,
rustc_do_not_implement_via_object,
rustc_doc_primitive,
rustc_driver,
rustc_dummy,
@ -1959,6 +1958,7 @@ symbols! {
rustc_dump_predicates,
rustc_dump_user_args,
rustc_dump_vtable,
rustc_dyn_incompatible_trait,
rustc_effective_visibility,
rustc_eii_foreign_item,
rustc_evaluate_where_clauses,

View file

@ -93,7 +93,10 @@ fn dyn_compatibility_violations_for_trait(
// We don't want to include the requirement from `Sized` itself to be `Sized` in the list.
let spans = get_sized_bounds(tcx, trait_def_id);
violations.push(DynCompatibilityViolation::SizedSelf(spans));
} else if let Some(span) = tcx.trait_def(trait_def_id).force_dyn_incompatible {
violations.push(DynCompatibilityViolation::ExplicitlyDynIncompatible([span].into()));
}
let spans = predicates_reference_self(tcx, trait_def_id, false);
if !spans.is_empty() {
violations.push(DynCompatibilityViolation::SupertraitSelf(spans));

View file

@ -799,10 +799,6 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
let tcx = selcx.tcx();
if !tcx.trait_def(obligation.predicate.trait_def_id(tcx)).implement_via_object {
return;
}
let self_ty = obligation.predicate.self_ty();
let object_ty = selcx.infcx.shallow_resolve(self_ty);
let data = match object_ty.kind() {

View file

@ -904,7 +904,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
"assemble_candidates_from_object_ty",
);
if !self.tcx().trait_def(obligation.predicate.def_id()).implement_via_object {
if self.tcx().is_sizedness_trait(obligation.predicate.def_id()) {
// `dyn MetaSized` is valid, but should get its `MetaSized` impl from
// being `dyn` (SizedCandidate), not from the object candidate.
return;
}

View file

@ -378,8 +378,6 @@ pub trait Interner:
fn trait_is_fundamental(self, def_id: Self::TraitId) -> bool;
fn trait_may_be_implemented_via_object(self, trait_def_id: Self::TraitId) -> bool;
/// Returns `true` if this is an `unsafe trait`.
fn trait_is_unsafe(self, trait_def_id: Self::TraitId) -> bool;

View file

@ -153,7 +153,7 @@ unsafe impl<T: Sync + PointeeSized> Send for &T {}
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
#[rustc_specialization_trait]
#[rustc_deny_explicit_impl]
#[rustc_do_not_implement_via_object]
#[rustc_dyn_incompatible_trait]
// `Sized` being coinductive, despite having supertraits, is okay as there are no user-written impls,
// and we know that the supertraits are always implemented if the subtrait is just by looking at
// the builtin impls.
@ -172,7 +172,6 @@ pub trait Sized: MetaSized {
#[fundamental]
#[rustc_specialization_trait]
#[rustc_deny_explicit_impl]
#[rustc_do_not_implement_via_object]
// `MetaSized` being coinductive, despite having supertraits, is okay for the same reasons as
// `Sized` above.
#[rustc_coinductive]
@ -190,7 +189,6 @@ pub trait MetaSized: PointeeSized {
#[fundamental]
#[rustc_specialization_trait]
#[rustc_deny_explicit_impl]
#[rustc_do_not_implement_via_object]
#[rustc_coinductive]
pub trait PointeeSized {
// Empty
@ -236,7 +234,7 @@ pub trait PointeeSized {
#[unstable(feature = "unsize", issue = "18598")]
#[lang = "unsize"]
#[rustc_deny_explicit_impl]
#[rustc_do_not_implement_via_object]
#[rustc_dyn_incompatible_trait]
pub trait Unsize<T: PointeeSized>: PointeeSized {
// Empty.
}
@ -509,7 +507,7 @@ impl<T: PointeeSized> Copy for &T {}
#[unstable(feature = "bikeshed_guaranteed_no_drop", issue = "none")]
#[lang = "bikeshed_guaranteed_no_drop"]
#[rustc_deny_explicit_impl]
#[rustc_do_not_implement_via_object]
#[rustc_dyn_incompatible_trait]
#[doc(hidden)]
pub trait BikeshedGuaranteedNoDrop {}
@ -884,7 +882,7 @@ impl<T: PointeeSized> StructuralPartialEq for PhantomData<T> {}
)]
#[lang = "discriminant_kind"]
#[rustc_deny_explicit_impl]
#[rustc_do_not_implement_via_object]
#[rustc_dyn_incompatible_trait]
pub trait DiscriminantKind {
/// The type of the discriminant, which must satisfy the trait
/// bounds required by `mem::Discriminant`.
@ -1054,7 +1052,7 @@ marker_impls! {
#[lang = "destruct"]
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
#[rustc_deny_explicit_impl]
#[rustc_do_not_implement_via_object]
#[rustc_dyn_incompatible_trait]
pub const trait Destruct: PointeeSized {}
/// A marker for tuple types.
@ -1065,7 +1063,7 @@ pub const trait Destruct: PointeeSized {}
#[lang = "tuple_trait"]
#[diagnostic::on_unimplemented(message = "`{Self}` is not a tuple")]
#[rustc_deny_explicit_impl]
#[rustc_do_not_implement_via_object]
#[rustc_dyn_incompatible_trait]
pub trait Tuple {}
/// A marker for types which can be used as types of `const` generic parameters.
@ -1123,7 +1121,7 @@ marker_impls! {
)]
#[lang = "fn_ptr_trait"]
#[rustc_deny_explicit_impl]
#[rustc_do_not_implement_via_object]
#[rustc_dyn_incompatible_trait]
pub trait FnPtr: Copy + Clone {
/// Returns the address of the function pointer.
#[lang = "fn_ptr_addr"]

View file

@ -86,7 +86,7 @@ use crate::marker::ConstParamTy_;
#[unstable_feature_bound(transmutability)]
#[lang = "transmute_trait"]
#[rustc_deny_explicit_impl]
#[rustc_do_not_implement_via_object]
#[rustc_dyn_incompatible_trait]
#[rustc_coinductive]
pub unsafe trait TransmuteFrom<Src, const ASSUME: Assume = { Assume::NOTHING }>
where

View file

@ -55,7 +55,7 @@ use crate::ptr::NonNull;
/// [`to_raw_parts`]: *const::to_raw_parts
#[lang = "pointee_trait"]
#[rustc_deny_explicit_impl]
#[rustc_do_not_implement_via_object]
#[rustc_dyn_incompatible_trait]
pub trait Pointee: PointeeSized {
/// The type for metadata in pointers and references to `Self`.
#[lang = "metadata_type"]

View file

@ -0,0 +1,25 @@
//@ run-pass
//! This test and `sized-*.rs` and `pointeesized.rs` test that dyn-compatibility correctly
//! handles sizedness traits, which are special in several parts of the compiler.
#![feature(sized_hierarchy)]
use std::marker::MetaSized;
trait Foo: std::fmt::Debug + MetaSized {}
impl<T: std::fmt::Debug + MetaSized> Foo for T {}
fn unsize_sized<T: 'static>(x: Box<T>) -> Box<dyn MetaSized> {
x
}
fn unsize_subtrait(x: Box<dyn Foo>) -> Box<dyn MetaSized> {
x
}
fn main() {
let _bx = unsize_sized(Box::new(vec![1, 2, 3]));
let bx: Box<dyn Foo> = Box::new(vec![1, 2, 3]);
let _ = format!("{bx:?}");
let _bx = unsize_subtrait(bx);
}

View file

@ -0,0 +1,17 @@
//@ run-pass
//! This test and `sized-*.rs` and `metasized.rs` test that dyn-compatibility correctly
//! handles sizedness traits, which are special in several parts of the compiler.
#![feature(sized_hierarchy)]
// PointeeSized is effectively removed before reaching the trait solver,
// so it's as though it wasn't even mentioned in the trait list.
use std::marker::PointeeSized;
fn main() {
let dyn_ref: &(dyn PointeeSized + Send) = &42;
let dyn_ref: &dyn Send = dyn_ref;
let _dyn_ref: &(dyn PointeeSized + Send) = dyn_ref;
assert_eq!(
std::any::TypeId::of::<dyn Send>(),
std::any::TypeId::of::<dyn PointeeSized + Send>(),
);
}

View file

@ -0,0 +1,29 @@
//! This test and `metasized.rs` and `pointeesized.rs` test that dyn-compatibility correctly
//! handles the different sizedness traits, which are special in several parts of the compiler.
trait Foo: std::fmt::Debug + Sized {}
impl<T: std::fmt::Debug + Sized> Foo for T {}
fn unsize_sized<T: 'static>(x: Box<T>) -> Box<dyn Sized> {
//~^ ERROR the trait `Sized` is not dyn compatible
x
}
fn unsize_subtrait(x: Box<dyn Foo>) -> Box<dyn Sized> {
//~^ ERROR the trait `Foo` is not dyn compatible
//~| ERROR the trait `Sized` is not dyn compatible
x
}
fn main() {
let _bx = unsize_sized(Box::new(vec![1, 2, 3]));
//~^ ERROR the trait `Sized` is not dyn compatible
let bx: Box<dyn Foo> = Box::new(vec![1, 2, 3]);
//~^ ERROR the trait `Foo` is not dyn compatible
let _ = format!("{bx:?}");
let _bx = unsize_subtrait(bx);
//~^ ERROR the trait `Foo` is not dyn compatible
//~| ERROR the trait `Sized` is not dyn compatible
}

View file

@ -0,0 +1,88 @@
error[E0038]: the trait `Sized` is not dyn compatible
--> $DIR/sized-3.rs:8:47
|
LL | fn unsize_sized<T: 'static>(x: Box<T>) -> Box<dyn Sized> {
| ^^^^^^^^^ `Sized` is not dyn compatible
|
= note: the trait is not dyn compatible because it requires `Self: Sized`
= note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
error[E0038]: the trait `Foo` is not dyn compatible
--> $DIR/sized-3.rs:13:27
|
LL | fn unsize_subtrait(x: Box<dyn Foo>) -> Box<dyn Sized> {
| ^^^^^^^ `Foo` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/sized-3.rs:4:30
|
LL | trait Foo: std::fmt::Debug + Sized {}
| --- ^^^^^ ...because it requires `Self: Sized`
| |
| this trait is not dyn compatible...
error[E0038]: the trait `Sized` is not dyn compatible
--> $DIR/sized-3.rs:13:44
|
LL | fn unsize_subtrait(x: Box<dyn Foo>) -> Box<dyn Sized> {
| ^^^^^^^^^ `Sized` is not dyn compatible
|
= note: the trait is not dyn compatible because it requires `Self: Sized`
= note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
error[E0038]: the trait `Sized` is not dyn compatible
--> $DIR/sized-3.rs:20:15
|
LL | let _bx = unsize_sized(Box::new(vec![1, 2, 3]));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Sized` is not dyn compatible
|
= note: the trait is not dyn compatible because it requires `Self: Sized`
= note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
error[E0038]: the trait `Foo` is not dyn compatible
--> $DIR/sized-3.rs:23:21
|
LL | let bx: Box<dyn Foo> = Box::new(vec![1, 2, 3]);
| ^^^ `Foo` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/sized-3.rs:4:30
|
LL | trait Foo: std::fmt::Debug + Sized {}
| --- ^^^^^ ...because it requires `Self: Sized`
| |
| this trait is not dyn compatible...
error[E0038]: the trait `Foo` is not dyn compatible
--> $DIR/sized-3.rs:26:31
|
LL | let _bx = unsize_subtrait(bx);
| ^^ `Foo` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/sized-3.rs:4:30
|
LL | trait Foo: std::fmt::Debug + Sized {}
| --- ^^^^^ ...because it requires `Self: Sized`
| |
| this trait is not dyn compatible...
error[E0038]: the trait `Sized` is not dyn compatible
--> $DIR/sized-3.rs:26:15
|
LL | let _bx = unsize_subtrait(bx);
| ^^^^^^^^^^^^^^^^^^^ `Sized` is not dyn compatible
|
= note: the trait is not dyn compatible because it requires `Self: Sized`
= note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0038`.

View file

@ -4,41 +4,67 @@ error[E0322]: explicit impls for the `NotImplYesObject` trait are not permitted
LL | impl NotImplYesObject for () {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `NotImplYesObject` not allowed
error[E0277]: the trait bound `dyn NotImplNotObject: NotImplNotObject` is not satisfied
--> $DIR/deny-builtin-object-impl.rs:37:32
error[E0038]: the trait `YesImplNotObject2` is not dyn compatible
--> $DIR/deny-builtin-object-impl.rs:23:28
|
LL | impl YesImplNotObject2 for dyn YesImplNotObject2 {}
| ^^^^^^^^^^^^^^^^^^^^^ `YesImplNotObject2` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/deny-builtin-object-impl.rs:17:1
|
LL | #[rustc_dyn_incompatible_trait]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility
LL | trait YesImplNotObject2 {}
| ----------------- this trait is not dyn compatible...
error[E0038]: the trait `NotImplNotObject` is not dyn compatible
--> $DIR/deny-builtin-object-impl.rs:37:36
|
LL | test_not_impl_not_object::<dyn NotImplNotObject>();
| ^^^^^^^^^^^^^^^^^^^^ the trait `NotImplNotObject` is not implemented for `dyn NotImplNotObject`
| ^^^^^^^^^^^^^^^^ `NotImplNotObject` is not dyn compatible
|
help: this trait has no implementations, consider adding one
--> $DIR/deny-builtin-object-impl.rs:12:1
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/deny-builtin-object-impl.rs:11:1
|
LL | #[rustc_dyn_incompatible_trait]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility
LL | trait NotImplNotObject {}
| ^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `test_not_impl_not_object`
--> $DIR/deny-builtin-object-impl.rs:28:32
|
LL | fn test_not_impl_not_object<T: NotImplNotObject + ?Sized>() {}
| ^^^^^^^^^^^^^^^^ required by this bound in `test_not_impl_not_object`
| ---------------- this trait is not dyn compatible...
error[E0277]: the trait bound `dyn YesImplNotObject: YesImplNotObject` is not satisfied
--> $DIR/deny-builtin-object-impl.rs:40:32
error[E0038]: the trait `YesImplNotObject` is not dyn compatible
--> $DIR/deny-builtin-object-impl.rs:40:36
|
LL | test_yes_impl_not_object::<dyn YesImplNotObject>();
| ^^^^^^^^^^^^^^^^^^^^ the trait `YesImplNotObject` is not implemented for `dyn YesImplNotObject`
| ^^^^^^^^^^^^^^^^ `YesImplNotObject` is not dyn compatible
|
help: this trait has no implementations, consider adding one
--> $DIR/deny-builtin-object-impl.rs:15:1
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/deny-builtin-object-impl.rs:14:1
|
LL | #[rustc_dyn_incompatible_trait]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility
LL | trait YesImplNotObject {}
| ^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `test_yes_impl_not_object`
--> $DIR/deny-builtin-object-impl.rs:30:32
| ---------------- this trait is not dyn compatible...
error[E0038]: the trait `YesImplNotObject2` is not dyn compatible
--> $DIR/deny-builtin-object-impl.rs:43:37
|
LL | fn test_yes_impl_not_object<T: YesImplNotObject + ?Sized>() {}
| ^^^^^^^^^^^^^^^^ required by this bound in `test_yes_impl_not_object`
LL | test_yes_impl_not_object2::<dyn YesImplNotObject2>();
| ^^^^^^^^^^^^^^^^^ `YesImplNotObject2` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/deny-builtin-object-impl.rs:17:1
|
LL | #[rustc_dyn_incompatible_trait]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility
LL | trait YesImplNotObject2 {}
| ----------------- this trait is not dyn compatible...
error: aborting due to 3 previous errors
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0277, E0322.
For more information about an error, try `rustc --explain E0277`.
Some errors have detailed explanations: E0038, E0322.
For more information about an error, try `rustc --explain E0038`.

View file

@ -4,41 +4,67 @@ error[E0322]: explicit impls for the `NotImplYesObject` trait are not permitted
LL | impl NotImplYesObject for () {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `NotImplYesObject` not allowed
error[E0277]: the trait bound `dyn NotImplNotObject: NotImplNotObject` is not satisfied
--> $DIR/deny-builtin-object-impl.rs:37:32
error[E0038]: the trait `YesImplNotObject2` is not dyn compatible
--> $DIR/deny-builtin-object-impl.rs:23:28
|
LL | impl YesImplNotObject2 for dyn YesImplNotObject2 {}
| ^^^^^^^^^^^^^^^^^^^^^ `YesImplNotObject2` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/deny-builtin-object-impl.rs:17:1
|
LL | #[rustc_dyn_incompatible_trait]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility
LL | trait YesImplNotObject2 {}
| ----------------- this trait is not dyn compatible...
error[E0038]: the trait `NotImplNotObject` is not dyn compatible
--> $DIR/deny-builtin-object-impl.rs:37:36
|
LL | test_not_impl_not_object::<dyn NotImplNotObject>();
| ^^^^^^^^^^^^^^^^^^^^ the trait `NotImplNotObject` is not implemented for `dyn NotImplNotObject`
| ^^^^^^^^^^^^^^^^ `NotImplNotObject` is not dyn compatible
|
help: this trait has no implementations, consider adding one
--> $DIR/deny-builtin-object-impl.rs:12:1
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/deny-builtin-object-impl.rs:11:1
|
LL | #[rustc_dyn_incompatible_trait]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility
LL | trait NotImplNotObject {}
| ^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `test_not_impl_not_object`
--> $DIR/deny-builtin-object-impl.rs:28:32
|
LL | fn test_not_impl_not_object<T: NotImplNotObject + ?Sized>() {}
| ^^^^^^^^^^^^^^^^ required by this bound in `test_not_impl_not_object`
| ---------------- this trait is not dyn compatible...
error[E0277]: the trait bound `dyn YesImplNotObject: YesImplNotObject` is not satisfied
--> $DIR/deny-builtin-object-impl.rs:40:32
error[E0038]: the trait `YesImplNotObject` is not dyn compatible
--> $DIR/deny-builtin-object-impl.rs:40:36
|
LL | test_yes_impl_not_object::<dyn YesImplNotObject>();
| ^^^^^^^^^^^^^^^^^^^^ the trait `YesImplNotObject` is not implemented for `dyn YesImplNotObject`
| ^^^^^^^^^^^^^^^^ `YesImplNotObject` is not dyn compatible
|
help: this trait has no implementations, consider adding one
--> $DIR/deny-builtin-object-impl.rs:15:1
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/deny-builtin-object-impl.rs:14:1
|
LL | #[rustc_dyn_incompatible_trait]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility
LL | trait YesImplNotObject {}
| ^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `test_yes_impl_not_object`
--> $DIR/deny-builtin-object-impl.rs:30:32
| ---------------- this trait is not dyn compatible...
error[E0038]: the trait `YesImplNotObject2` is not dyn compatible
--> $DIR/deny-builtin-object-impl.rs:43:37
|
LL | fn test_yes_impl_not_object<T: YesImplNotObject + ?Sized>() {}
| ^^^^^^^^^^^^^^^^ required by this bound in `test_yes_impl_not_object`
LL | test_yes_impl_not_object2::<dyn YesImplNotObject2>();
| ^^^^^^^^^^^^^^^^^ `YesImplNotObject2` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/deny-builtin-object-impl.rs:17:1
|
LL | #[rustc_dyn_incompatible_trait]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatibility
LL | trait YesImplNotObject2 {}
| ----------------- this trait is not dyn compatible...
error: aborting due to 3 previous errors
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0277, E0322.
For more information about an error, try `rustc --explain E0277`.
Some errors have detailed explanations: E0038, E0322.
For more information about an error, try `rustc --explain E0038`.

View file

@ -8,20 +8,20 @@
trait NotImplYesObject {}
#[rustc_deny_explicit_impl]
#[rustc_do_not_implement_via_object]
#[rustc_dyn_incompatible_trait]
trait NotImplNotObject {}
#[rustc_do_not_implement_via_object]
#[rustc_dyn_incompatible_trait]
trait YesImplNotObject {}
#[rustc_do_not_implement_via_object]
#[rustc_dyn_incompatible_trait]
trait YesImplNotObject2 {}
impl NotImplYesObject for () {}
//~^ ERROR explicit impls for the `NotImplYesObject` trait are not permitted
// If there is no automatic impl then we can add a manual impl:
impl YesImplNotObject2 for dyn YesImplNotObject2 {}
//~^ ERROR the trait `YesImplNotObject2` is not dyn compatible
fn test_not_impl_yes_object<T: NotImplYesObject + ?Sized>() {}
@ -35,10 +35,11 @@ fn main() {
test_not_impl_yes_object::<dyn NotImplYesObject>();
test_not_impl_not_object::<dyn NotImplNotObject>();
//~^ ERROR the trait bound `dyn NotImplNotObject: NotImplNotObject` is not satisfied
//~^ ERROR the trait `NotImplNotObject` is not dyn compatible
test_yes_impl_not_object::<dyn YesImplNotObject>();
//~^ ERROR the trait bound `dyn YesImplNotObject: YesImplNotObject` is not satisfied
//~^ ERROR the trait `YesImplNotObject` is not dyn compatible
test_yes_impl_not_object2::<dyn YesImplNotObject2>();
//~^ ERROR the trait `YesImplNotObject2` is not dyn compatible
}

View file

@ -6,10 +6,12 @@ use core::ptr::Pointee;
fn unknown_sized_object_ptr_in(_: &(impl Pointee<Metadata = ()> + ?Sized)) {}
fn raw_pointer_in(x: &dyn Pointee<Metadata = ()>) {
//~^ ERROR the trait `Pointee` is not dyn compatible
unknown_sized_object_ptr_in(x)
//~^ ERROR type mismatch resolving `<dyn Pointee<Metadata = ()> as Pointee>::Metadata == ()`
//~^ ERROR the trait `Pointee` is not dyn compatible
}
fn main() {
raw_pointer_in(&42)
//~^ ERROR the trait `Pointee` is not dyn compatible
}

View file

@ -1,19 +1,39 @@
error[E0271]: type mismatch resolving `<dyn Pointee<Metadata = ()> as Pointee>::Metadata == ()`
--> $DIR/ice-with-dyn-pointee-errors.rs:9:33
error[E0038]: the trait `Pointee` is not dyn compatible
--> $DIR/ice-with-dyn-pointee-errors.rs:8:23
|
LL | fn raw_pointer_in(x: &dyn Pointee<Metadata = ()>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `Pointee` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
|
= note: the trait is not dyn compatible because it opted out of dyn-compatibility
error[E0038]: the trait `Pointee` is not dyn compatible
--> $DIR/ice-with-dyn-pointee-errors.rs:10:5
|
LL | unknown_sized_object_ptr_in(x)
| --------------------------- ^ expected `()`, found `DynMetadata<dyn Pointee<Metadata = ()>>`
| |
| required by a bound introduced by this call
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Pointee` is not dyn compatible
|
= note: expected unit type `()`
found struct `DynMetadata<dyn Pointee<Metadata = ()>>`
note: required by a bound in `unknown_sized_object_ptr_in`
--> $DIR/ice-with-dyn-pointee-errors.rs:6:50
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
|
LL | fn unknown_sized_object_ptr_in(_: &(impl Pointee<Metadata = ()> + ?Sized)) {}
| ^^^^^^^^^^^^^ required by this bound in `unknown_sized_object_ptr_in`
= note: the trait is not dyn compatible because it opted out of dyn-compatibility
error: aborting due to 1 previous error
error[E0038]: the trait `Pointee` is not dyn compatible
--> $DIR/ice-with-dyn-pointee-errors.rs:15:20
|
LL | raw_pointer_in(&42)
| ^^^ `Pointee` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
|
= note: the trait is not dyn compatible because it opted out of dyn-compatibility
For more information about this error, try `rustc --explain E0271`.
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0038`.

View file

@ -1,11 +0,0 @@
//@ run-pass
#![feature(ptr_metadata)]
// Address issue #112737 -- ICE with dyn Pointee
extern crate core;
use core::ptr::Pointee;
fn raw_pointer_in(_: &dyn Pointee<Metadata = ()>) {}
fn main() {
raw_pointer_in(&42)
}

View file

@ -1,18 +1,22 @@
error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied
--> $DIR/issue-71659.rs:34:15
error[E0038]: the trait `Foo` is not dyn compatible
--> $DIR/issue-71659.rs:33:17
|
LL | let x = x.cast::<[i32]>();
| ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
LL | let x: &dyn Foo = &[];
| ^^^ `Foo` is not dyn compatible
|
note: required by a bound in `Cast::cast`
--> $DIR/issue-71659.rs:23:15
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $SRC_DIR/core/src/marker.rs:LL:COL
|
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`
= note: ...because it opted out of dyn-compatibility
|
::: $DIR/issue-71659.rs:29:11
|
LL | pub trait Foo: CastTo<[i32]> {}
| --- this trait is not dyn compatible...
= help: only type `[i32; 0]` implements `Foo` within this crate; consider using it directly instead.
= note: `Foo` may be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0038`.

View file

@ -1,18 +1,22 @@
error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied
--> $DIR/issue-71659.rs:34:15
error[E0038]: the trait `Foo` is not dyn compatible
--> $DIR/issue-71659.rs:33:17
|
LL | let x = x.cast::<[i32]>();
| ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
LL | let x: &dyn Foo = &[];
| ^^^ `Foo` is not dyn compatible
|
note: required by a bound in `Cast::cast`
--> $DIR/issue-71659.rs:23:15
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $SRC_DIR/core/src/marker.rs:LL:COL
|
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`
= note: ...because it opted out of dyn-compatibility
|
::: $DIR/issue-71659.rs:29:11
|
LL | pub trait Foo: CastTo<[i32]> {}
| --- this trait is not dyn compatible...
= help: only type `[i32; 0]` implements `Foo` within this crate; consider using it directly instead.
= note: `Foo` may be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.
For more information about this error, try `rustc --explain E0038`.

View file

@ -31,6 +31,6 @@ impl Foo for [i32; 0] {}
fn main() {
let x: &dyn Foo = &[];
//~^ ERROR: the trait `Foo` is not dyn compatible
let x = x.cast::<[i32]>();
//~^ ERROR: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied
}