Skip to content

Commit 8236a96

Browse files
authored
Unrolled build for #148637
Rollup merge of #148637 - rustc_dyn_incompatible, r=lcnr Replace `#[rustc_do_not_implement_via_object]` with `#[rustc_dyn_incompatible_trait]` Background: `#[rustc_do_not_implement_via_object]` on a trait currently still allows `dyn Trait` to exist (if the trait is otherwise dyn-compatible), it just means that `dyn Trait` does not automatically implement `Trait` via the normal object candidate. For some traits, this means that `dyn Trait` does not implement `Trait` at all (e.g. `Unsize` and `Tuple`). For some traits, this means that `dyn Trait` implements `Trait`, but with different associated types (e.g. `Pointee`, `DiscriminantKind`). Both of these cases can can cause issues with codegen , as seen in #148089 (and #148089 (comment) ), because codegen assumes that if `dyn Trait` does not implement `Trait` (including if `dyn Trait<Assoc = T>` does not implement `Trait` with `Assoc == T`), then `dyn Trait` cannot be constructed, so vtable accesses on `dyn Trait` are unreachable, but this is not the case if `dyn Trait` has multiple supertraits: one which is `#[rustc_do_not_implement_via_object]`, and one which we are doing the vtable access to call a method from. This PR replaces `#[rustc_do_not_implement_via_object]` with `#[rustc_dyn_incompatible_trait]`, which makes the marked trait dyn-incompatible, making `dyn Trait` not well-formed, instead of it being well-formed but not implementing `Trait`. This resolves #148089 by making it not compile. May fix #148615 The traits that are currently marked `#[rustc_do_not_implement_via_object]` are: `Sized`, `MetaSized`, `PointeeSized`, `TransmuteFrom`, `Unsize`, `BikeshedGuaranteedNoDrop`, `DiscriminantKind`, `Destruct`, `Tuple`, `FnPtr`, `Pointee`. Of these: * `Sized` and `FnPtr` are already not dyn-compatible (`FnPtr: Copy`, which implies `Sized`) * `MetaSized` * Removed `#[rustc_do_not_implement_via_object]`. Still dyn-compatible after this change. (Has a special-case in the trait solvers to ignore the object candidate for `dyn MetaSized`, since it `dyn MetaSized: MetSized` comes from the sized candidate that all `dyn Trait` get.) * `PointeeSized` * Removed `#[rustc_do_not_implement_via_object]`. It doesn't seem to have been doing anything anyway ([playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=a395626c8bef791b87a2d371777b7841)), since `PointeeSized` is removed before trait solving(?). * `Pointee`, `DiscriminantKind`, `Unsize`, and `Tuple` being dyn-compatible without having `dyn Trait: Trait` (with same assoc tys) can be observed to cause codegen issues (#148089) so should be made dyn-incompatible * `Destruct`, `TransmuteFrom`, and `BikeshedGuaranteedNoDrop` I'm not sure if would be useful as object types, but they can be relaxed to being dyn-compatible later if it is determined they should be. ----- <details> <summary> resolved </summary> Questions before merge: 1. `dyn MetaSized: MetaSized` having both `SizedCandidate` and `ObjectCandidate` 1. I'm not sure if the checks in compiler/rustc_trait_selection/src/traits/project.rs and compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs were "load-bearing" for `MetaSized` (which is the only trait that was previously `#[rustc_do_not_implement_via_object]` that is still dyn-compatible after this change). Is it fine to just remove them? Removing them (as I did in the second commit) doesn't change any UI test results. 3. IIUC, `dyn MetaSized` could get its `MetaSized` implementation in two ways: the object candidate (the normal `dyn Trait: Trait`) that was supressed by `#[rustc_do_not_implement_via_object]`, and the `SizedCandidate` (that all `dyn Trait` get for `dyn Trait: MetaSized`). Given that `MetaSized` has no associated types or methods, is it fine that these both exist now? Or is it better to only have the `SizedCandidate` and leave these checks in (i.e. drop the second commit, and remove the FIXMEs)? 4. Resolved: the trait solvers special-case `dyn MetaSized` to ignore the object candidate in preference to the sizedness candidate (technically the check is for any `is_sizedness_trait`, but only `MetaSized` gets this far (`Sized` is inherently dyn-incompatible, and `dyn PointeeSized` is ill-formed for other reasons) 4. Diagnostics improvements? 1. The diagnostics are kinda bad. If you have a `trait Foo: Pointee {}`, you now get a note that reads like *Foo* "opted out of dyn-compatbility", when really `Pointee` did that. 2. Resolved: can be improved later <details> <summary>diagnostic example</summary> ```rs #![feature(ptr_metadata)] trait C: std::ptr::Pointee {} fn main() { let y: &dyn C; } ``` ```rs error[E0038]: the trait `C` is not dyn compatible --> c.rs:6:17 | 6 | let y: &dyn C; | ^ `C` 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> --> /home/zachary/opt_mount/zachary/Programming/rust-compiler-2/library/core/src/ptr/metadata.rs:57:1 | 57 | #[rustc_dyn_incompatible_trait] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it opted out of dyn-compatbility | ::: c.rs:3:7 | 3 | trait C: std::ptr::Pointee {} | - this trait is not dyn compatible... error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0038`. ``` </details> </details> Still investigating "3. `compiler/rustc_hir/src/attrs/encode_cross_crate.rs`: Should `DynIncompatibleTrait` attribute be encoded cross crate?"
2 parents 88ad3d4 + c3205f9 commit 8236a96

35 files changed

Lines changed: 387 additions & 154 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/traits.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,12 @@ impl<S: Stage> NoArgsAttributeParser<S> for DenyExplicitImplParser {
9494
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DenyExplicitImpl;
9595
}
9696

97-
pub(crate) struct DoNotImplementViaObjectParser;
98-
impl<S: Stage> NoArgsAttributeParser<S> for DoNotImplementViaObjectParser {
99-
const PATH: &[Symbol] = &[sym::rustc_do_not_implement_via_object];
97+
pub(crate) struct DynIncompatibleTraitParser;
98+
impl<S: Stage> NoArgsAttributeParser<S> for DynIncompatibleTraitParser {
99+
const PATH: &[Symbol] = &[sym::rustc_dyn_incompatible_trait];
100100
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
101101
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
102-
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DoNotImplementViaObject;
102+
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DynIncompatibleTrait;
103103
}
104104

105105
// Specialization

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ use crate::attributes::test_attrs::{
9090
};
9191
use crate::attributes::traits::{
9292
AllowIncoherentImplParser, CoinductiveParser, DenyExplicitImplParser,
93-
DoNotImplementViaObjectParser, FundamentalParser, MarkerParser, ParenSugarParser,
94-
PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser,
93+
DynIncompatibleTraitParser, FundamentalParser, MarkerParser, ParenSugarParser, PointeeParser,
94+
SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser,
9595
UnsafeSpecializationMarkerParser,
9696
};
9797
use crate::attributes::transparency::TransparencyParser;
@@ -255,7 +255,7 @@ attribute_parsers!(
255255
Single<WithoutArgs<ConstStabilityIndirectParser>>,
256256
Single<WithoutArgs<CoroutineParser>>,
257257
Single<WithoutArgs<DenyExplicitImplParser>>,
258-
Single<WithoutArgs<DoNotImplementViaObjectParser>>,
258+
Single<WithoutArgs<DynIncompatibleTraitParser>>,
259259
Single<WithoutArgs<EiiForeignItemParser>>,
260260
Single<WithoutArgs<ExportStableParser>>,
261261
Single<WithoutArgs<FfiConstParser>>,

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,13 +1315,13 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
13151315
"`#[rustc_deny_explicit_impl]` enforces that a trait can have no user-provided impls"
13161316
),
13171317
rustc_attr!(
1318-
rustc_do_not_implement_via_object,
1318+
rustc_dyn_incompatible_trait,
13191319
AttributeType::Normal,
13201320
template!(Word),
13211321
ErrorFollowing,
13221322
EncodeCrossCrate::No,
1323-
"`#[rustc_do_not_implement_via_object]` opts out of the automatic trait impl for trait objects \
1324-
(`impl Trait for dyn Trait`)"
1323+
"`#[rustc_dyn_incompatible_trait]` marks a trait as dyn-incompatible, \
1324+
even if it otherwise satisfies the requirements to be dyn-compatible."
13251325
),
13261326
rustc_attr!(
13271327
rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word),

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -728,9 +728,6 @@ pub enum AttributeKind {
728728
/// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
729729
Deprecation { deprecation: Deprecation, span: Span },
730730

731-
/// Represents `#[rustc_do_not_implement_via_object]`.
732-
DoNotImplementViaObject(Span),
733-
734731
/// Represents `#[diagnostic::do_not_recommend]`.
735732
DoNotRecommend { attr_span: Span },
736733

@@ -746,6 +743,9 @@ pub enum AttributeKind {
746743
/// Represents `#[rustc_dummy]`.
747744
Dummy,
748745

746+
/// Represents `#[rustc_dyn_incompatible_trait]`.
747+
DynIncompatibleTrait(Span),
748+
749749
/// Implementation detail of `#[eii]`
750750
EiiDeclaration(EiiDecl),
751751

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ impl AttributeKind {
4343
DebuggerVisualizer(..) => No,
4444
DenyExplicitImpl(..) => No,
4545
Deprecation { .. } => Yes,
46-
DoNotImplementViaObject(..) => No,
4746
DoNotRecommend { .. } => Yes,
4847
Doc(_) => Yes,
4948
DocComment { .. } => Yes,
5049
Dummy => No,
50+
DynIncompatibleTrait(..) => No,
5151
EiiDeclaration(_) => Yes,
5252
EiiForeignItem => No,
5353
EiiImpls(..) => No,

compiler/rustc_hir_analysis/src/coherence/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,7 @@ fn check_object_overlap<'tcx>(
211211
// This is a WF error tested by `coherence-impl-trait-for-trait-dyn-compatible.rs`.
212212
} else {
213213
let mut supertrait_def_ids = elaborate::supertrait_def_ids(tcx, component_def_id);
214-
if supertrait_def_ids
215-
.any(|d| d == trait_def_id && tcx.trait_def(d).implement_via_object)
216-
{
214+
if supertrait_def_ids.any(|d| d == trait_def_id) {
217215
let span = tcx.def_span(impl_def_id);
218216
return Err(struct_span_code_err!(
219217
tcx.dcx(),

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -924,7 +924,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
924924
);
925925

926926
let deny_explicit_impl = find_attr!(attrs, AttributeKind::DenyExplicitImpl(_));
927-
let implement_via_object = !find_attr!(attrs, AttributeKind::DoNotImplementViaObject(_));
927+
let force_dyn_incompatible =
928+
find_attr!(attrs, AttributeKind::DynIncompatibleTrait(span) => *span);
928929

929930
ty::TraitDef {
930931
def_id: def_id.to_def_id(),
@@ -939,7 +940,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
939940
skip_boxed_slice_during_method_dispatch,
940941
specialization_kind,
941942
must_implement_one_of,
942-
implement_via_object,
943+
force_dyn_incompatible,
943944
deny_explicit_impl,
944945
}
945946
}

compiler/rustc_middle/src/traits/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,9 @@ pub enum DynCompatibilityViolation {
764764
/// `Self: Sized` declared on the trait.
765765
SizedSelf(SmallVec<[Span; 1]>),
766766

767+
/// Trait is marked `#[rustc_dyn_incompatible_trait]`.
768+
ExplicitlyDynIncompatible(SmallVec<[Span; 1]>),
769+
767770
/// Supertrait reference references `Self` an in illegal location
768771
/// (e.g., `trait Foo : Bar<Self>`).
769772
SupertraitSelf(SmallVec<[Span; 1]>),
@@ -788,6 +791,9 @@ impl DynCompatibilityViolation {
788791
pub fn error_msg(&self) -> Cow<'static, str> {
789792
match self {
790793
DynCompatibilityViolation::SizedSelf(_) => "it requires `Self: Sized`".into(),
794+
DynCompatibilityViolation::ExplicitlyDynIncompatible(_) => {
795+
"it opted out of dyn-compatibility".into()
796+
}
791797
DynCompatibilityViolation::SupertraitSelf(spans) => {
792798
if spans.iter().any(|sp| *sp != DUMMY_SP) {
793799
"it uses `Self` as a type parameter".into()
@@ -861,6 +867,7 @@ impl DynCompatibilityViolation {
861867
pub fn solution(&self) -> DynCompatibilityViolationSolution {
862868
match self {
863869
DynCompatibilityViolation::SizedSelf(_)
870+
| DynCompatibilityViolation::ExplicitlyDynIncompatible(_)
864871
| DynCompatibilityViolation::SupertraitSelf(_)
865872
| DynCompatibilityViolation::SupertraitNonLifetimeBinder(..)
866873
| DynCompatibilityViolation::SupertraitConst(_) => {
@@ -894,6 +901,7 @@ impl DynCompatibilityViolation {
894901
match self {
895902
DynCompatibilityViolation::SupertraitSelf(spans)
896903
| DynCompatibilityViolation::SizedSelf(spans)
904+
| DynCompatibilityViolation::ExplicitlyDynIncompatible(spans)
897905
| DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans)
898906
| DynCompatibilityViolation::SupertraitConst(spans) => spans.clone(),
899907
DynCompatibilityViolation::AssocConst(_, span)

compiler/rustc_middle/src/ty/context.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -709,10 +709,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
709709
self.trait_def(def_id).is_fundamental
710710
}
711711

712-
fn trait_may_be_implemented_via_object(self, trait_def_id: DefId) -> bool {
713-
self.trait_def(trait_def_id).implement_via_object
714-
}
715-
716712
fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool {
717713
self.trait_def(trait_def_id).safety.is_unsafe()
718714
}

compiler/rustc_middle/src/ty/trait_def.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_hir::def::DefKind;
77
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
88
use rustc_hir::{self as hir, find_attr};
99
use rustc_macros::{Decodable, Encodable, HashStable};
10+
use rustc_span::Span;
1011
use tracing::debug;
1112

1213
use crate::query::LocalCrate;
@@ -69,10 +70,9 @@ pub struct TraitDef {
6970
/// must be implemented.
7071
pub must_implement_one_of: Option<Box<[Ident]>>,
7172

72-
/// Whether to add a builtin `dyn Trait: Trait` implementation.
73-
/// This is enabled for all traits except ones marked with
74-
/// `#[rustc_do_not_implement_via_object]`.
75-
pub implement_via_object: bool,
73+
/// Whether the trait should be considered dyn-incompatible, even if it otherwise
74+
/// satisfies the requirements to be dyn-compatible.
75+
pub force_dyn_incompatible: Option<Span>,
7676

7777
/// Whether a trait is fully built-in, and any implementation is disallowed.
7878
/// This only applies to built-in traits, and is marked via

0 commit comments

Comments
 (0)