trait Object<U> {
type Output;
}
impl<T: ?Sized, U> Object<U> for T {
// ^-- Here is the blanket impl; relies on `?Sized`.
type Output = U;
fn foo<T: ?Sized, U>(x: <T as Object<U>>::Output) -> U {
x
fn transmute<T, U>(x: T) -> U {
foo::<dyn Object<U, Output = T>, U>(x)
// trait MyWrite: Write
impl<T: Write + ?Sized> MyWrite for T {
fn my_write(&self) { self.write(); }
fn foo<T: ?Sized + Any>(x: &T) {
let foo = x.type_id();
// Upstream crate
impl<A> Object for A {
default type Output = ();
fn foo<T>() {
let y: T::Output = ..;
// before specialization: T::Output = ()
// after specialization: T::Output kept as a placeholder
Background gist
trait Object<U> {
type Output;
}
impl<T: ?Sized, U> Object<U> for T {
// ^-- Here is the blanket impl; relies on `?Sized`.
type Output = U;
}
fn foo<T: ?Sized, U>(x: <T as Object<U>>::Output) -> U {
x
}
fn transmute<T, U>(x: T) -> U {
foo::<dyn Object<U, Output = T>, U>(x)
}
Notes from meeting
why have a vtable impl?
// trait MyWrite: Write
impl<T: Write + ?Sized> MyWrite for T {
fn my_write(&self) { self.write(); }
}
fn foo<T: ?Sized + Any>(x: &T) {
let foo = x.type_id();
}
// Upstream crate
impl<A> Object for A {
default type Output = ();
}
fn foo<T>() {
let y: T::Output = ..;
// before specialization: T::Output = ()
// after specialization: T::Output kept as a placeholder
}