Closed
Description
One of the requirements for a trait to be object-safe is that the associated types that show up in signatures of methods come from the supertraits of the object. We don't currently implement this correctly -- we currently ignore the substitutions of the associated type 😿.
This is unsound:
use core::marker::PhantomData;
fn transmute<T, U>(t: T) -> U {
(&PhantomData::<T> as &dyn Foo<T, U>).transmute(t)
}
struct ActuallySuper;
struct NotActuallySuper;
trait Super<Q> {
type Assoc;
}
trait Dyn {
type Out;
}
impl<T, U> Dyn for dyn Foo<T, U> + '_ {
type Out = U;
}
impl<S: Dyn<Out = U> + ?Sized, U> Super<NotActuallySuper> for S {
type Assoc = U;
}
trait Foo<T, U>: Super<ActuallySuper, Assoc = T> where <Self as Mirror>::Assoc: Super<NotActuallySuper> {
fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc;
}
trait Mirror {
type Assoc: ?Sized;
}
impl<T: ?Sized> Mirror for T {
type Assoc = T;
}
impl<T, U> Foo<T, U> for PhantomData<T> {
fn transmute(&self, t: T) -> T {
t
}
}
impl<T> Super<ActuallySuper> for PhantomData<T> {
type Assoc = T;
}
impl<T> Super<NotActuallySuper> for PhantomData<T> {
type Assoc = T;
}
fn main() {
let x = String::from("hello, world");
let s = transmute::<&str, &'static str>(x.as_str());
drop(x);
println!("> {s}");
}
Specifically, fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc;
should only be sound if the return type was <Self as Super<ActuallySuper>>::Assoc
, or if we added Super<NotActuallySuper>
as a supertrait.
We should probably deeply normalize these supertraits and actually consider the associated types' substs match modulo regions.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Completed