projecting to assoc type of supertrait that is implemented differently for trait object goes wrong
Opened this issue · 5 comments
I tried this code: playground
#![feature(ptr_metadata)]
use std::ptr::Pointee;
trait Trait: Pointee {
fn meta(&self) -> Self::Metadata;
}
impl Trait for () {
fn meta(&self) {}
}
fn main() {
let d: &dyn Trait<Metadata = ()> = &();
let m = d.meta();
dbg!(m);
}I expected to see this happen: The type of m is () (or Trait is dyn incompatible).
Instead, this happened: The type of m is DynMetadata<dyn Trait<Metadata = ()>>.
Presumably this affects all traits with #[rustc_deny_explicit_impl(implement_via_object = false)] and associated types.
Miri does report UB for this code:
error: Undefined Behavior: calling a function with return type () passing return place of type std::ptr::DynMetadata<dyn Trait<Metadata = ()>>
--> src/main.rs:15:13
|
15 | let m = d.meta();
| ^^^^^^^^ calling a function with return type () passing return place of type std::ptr::DynMetadata<dyn Trait<Metadata = ()>>
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
= help: if you think this code should be accepted anyway, please report an issue with Miri
= note: BACKTRACE:
= note: inside `main` at src/main.rs:15:13: 15:21
Meta
playground nightly
Build using the Nightly version: 1.84.0-nightly
(2024-10-17 3ed6e3cc69857129c1d3)
@rustbot label A-trait-objects A-associated-items T-types I-unsound requires-nightly -needs-triage
Reminds me of the unsoundness with Any trait overlap except for projections, and in this case an overlap between built-in impls and objects... I'll look into it later today after breakfast.
@rustbot claim
We have two choices:
- Treat all
#[rustc_deny_explicit_impl(implement_via_object = false)]as object-unsafe. - Reject supertrait associated types from signatures if they come from supertraits that are
#[rustc_deny_explicit_impl(implement_via_object = false)].
- Treat assoc items of
#[rustc_deny_explicit_impl(implement_via_object = false)]traits as not coming from a supertrait for the dyn compatibility check only.
(i.e. ignore supertraits withimplement_via_object = falsehere:)rust/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
Lines 812 to 847 in d9eb6d8
Sorry, yes, that's what I meant for (2.). Specifically, they're as-if they came from a non supertrait.
Related issue: #148203