# 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