# dyn trait upcasting ```rust trait Foo { } trait Bar: Foo { } fn foo(x: &dyn Foo) { } fn bar(x: &dyn Bar) { foo(x); } fn main() { } ``` * subtyping and coercion * we expect this to operate via coercion * so e.g. `&[&dyn Bar]` cannot be upcast to `&[&dyn Foo]` * this would require *subtyping* * representation of `dyn Foo` and `dyn Bar` are not the same * `dyn Foo` has a vtable for `Foo` * `dyn Bar` has a vtable for `Bar` * operation at runtime: * `dyn Bar` has a vtable `V_Bar` for `Bar` * embedded in that vtable has to be a vtable for each supertrait * extract the vtable `V_Foo` for `Foo` from `V_Bar` * and build a new fat pointer that has the same data pointer + `V_Foo` * cannot coerce through indirection * you can only coerce what you own * can coerce T to U * but can't coerce &T to &U * `[&dyn Bar; 2]` to `[&dyn Foo; 2]` could in principle work * but we don't do that * we also don't do `(&dyn Bar, &dyn Bar)` to `(&dyn Foo, &dyn Foo)` * implemented in a monster PR [#60900](https://github.com/rust-lang/rust/pull/60900) * some similar logic exists already, which allows this to compile: ```rust trait Foo { } trait Bar: Foo { } fn foo(x: &dyn Foo) { } fn bar<T: Bar>(x: &T) { foo(x); } fn main() { } ``` * in fact there is already an even closer coercion to what we want * `dyn Bar + 'a` to `dyn Bar + 'b` * if `'a: 'b` * also allow you to change autotraits -- so e.g. `dyn Foo + Send + Sync` can be coerced to `dyn Foo + Sync` * [code](https://github.com/rust-lang/rust/blob/3d3c8c5e0d534cdd794f1b3359089eba031d492c/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs#L701-L719) * what are the steps we have to do to make this change? * extend the vtable format to include vtables for supertraits * purely cost, vtables get bigger, and we never use that data * [old PR](https://github.com/rust-lang/rust/pull/60900/files#diff-2e9dc99a33a1e6ce2e4e3e154be6d7355cc4fd9dc139210d970d1e5d19f28d72R59) * introduce the vtable coercion code * [old PR](https://github.com/rust-lang/rust/pull/60900/files#diff-4e1a065bece9418b851aa22b5061868bccd94bbfb3d4aeeb06e0e98350aa5480R259) * introduce the feature gate * trait coercion changes (marked by feature gate) * [old PR](https://github.com/rust-lang/rust/pull/60900/files#diff-330b885d1e6c5fd2b6785b08d66e6c497f5c68a9c5a008c98aea0f7d98c9597dR1858) * add tests * extend rustc-dev-guide with: * coverage of the vtable format and where that is implemented in the code * whatever else seems good * what process do we need to make this change? * do we need an RFC? * need some sort of write-up