# Why it is not allowed to cast &T to &dyn Trait, where T: Trait + ?Sized?

**URL:** <https://users.rust-lang.org/t/why-it-is-not-allowed-to-cast-t-to-dyn-trait-where-t-trait-sized/110969>\
**Category:** help\
**Created:** [May 6, 2024, 12:20pm UTC](https://users.rust-lang.org/t/why-it-is-not-allowed-to-cast-t-to-dyn-trait-where-t-trait-sized/110969 "2024-05-06T12:20:29Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![user1984](https://avatars.discourse-cdn.com/v4/letter/u/ebca7d/32.png) [@user1984](https://users.rust-lang.org/u/user1984)\
**Post date:** [May 6, 2024, 12:20pm UTC](https://users.rust-lang.org/t/why-it-is-not-allowed-to-cast-t-to-dyn-trait-where-t-trait-sized/110969/1 "2024-05-06T12:20:29Z")

</div>

Hello.

I observe that casting &T to &dyn Trait, where T: Trait, is allowed only if the size of T is known at compile time, that is, T: Sized.

That is, the compilation of the following code results in an error:

```rust
trait Trait {}

fn mycast<T: Trait + ?Sized>(t: &T) {
    let _: &dyn Trait = t; // the size for values of type `T` cannot be known at compilation time
}

```

As far as I understand, internally `&dyn Trait` is represented as a fat pointer, a kind of tuple consisting of `(*const T, *const Vtable<Trait, T>)`.  
I don't see why it may be technically impossible to create such a fat pointer; both the pointer to T (`&T` is `*const T` internally), and the vtable of trait `Trait` for type `T` should be known during the convertion, as both `T` and `Trait` are known at compile time.

Yet, the compiler doesn't allow such a convertion. What is the reason behind that? Is that technically impossible, or it is unsafe (if so, why ?), or some other reason?  
Thanks!

---

<div class="post-metadata">

**Author:** ![jonh](https://avatars.discourse-cdn.com/v4/letter/j/dec6dc/32.png) [@jonh](https://users.rust-lang.org/u/jonh)\
**Post date:** [May 6, 2024, 12:58pm UTC](https://users.rust-lang.org/t/why-it-is-not-allowed-to-cast-t-to-dyn-trait-where-t-trait-sized/110969/2 "2024-05-06T12:58:11Z")

</div>

`&T` is also a fat pointer when not `Sized`. The type could be a slice with the extra being the length. The code does not get to forget the length when referring to a trait object.

---

<div class="post-metadata">

**Author:** ![khimru](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/khimru/32/31344_2.png) [@khimru](https://users.rust-lang.org/u/khimru)\
**Post date:** [May 6, 2024, 2:44pm UTC](https://users.rust-lang.org/t/why-it-is-not-allowed-to-cast-t-to-dyn-trait-where-t-trait-sized/110969/3 "2024-05-06T14:44:25Z")

</div>

> [@user1984](#):
>
> Yet, the compiler doesn't allow such a convertion. What is the reason behind that? Is that technically impossible, or it is unsafe (if so, why ?), or some other reason?

Limitation of the compiler, yet one that we have to live with. Fat pointer in Rust includes precisely two things: pointer to objects and… another pointer-sized word. This word is pointer to vtable for `dyn` or `length` for slice or something else, but “very fat pointers” are not supported.

One may imagine a different language where “very fat pointers” and, maybe, “unsized pointers” are supported… but that would be a different language, not Rust.

> [@user1984](#):
>
> I don't see why it may be technically impossible to create such a fat pointer; both the pointer to T (`&T` is `*const T` internally), and the vtable of trait `Trait` for type `T` should be known during the convertion, as both `T` and `Trait` are known at compile time.

If `T` is unsized then you need to put it's size somewhere. One may imagine that compiler would create vtable on the fly and put it there (Swift does something likes this [for very different reason](https://faultlore.com/blah/swift-abi/)), but, again, Rust is not designed to have hidden allocations in random places.

> [@user1984](#):
>
> Is that technically impossible, or it is unsafe (if so, why ?), or some other reason?

You would need to rethink some design decisions that Rust did to allow that.

Not impossible in some other language, but given the constraints that Rust have (no “arbitrarily fat” pointers, not hidden allocations) we are stuck with what we have.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/scottmcm/32/4286_2.png) [@scottmcm](https://users.rust-lang.org/u/scottmcm)\
**Post date:** [May 6, 2024, 5:52pm UTC](https://users.rust-lang.org/t/why-it-is-not-allowed-to-cast-t-to-dyn-trait-where-t-trait-sized/110969/4 "2024-05-06T17:52:08Z")

</div>

The other posts here are good for why it works like this, but it made me think that we ought to have a "do the right thing" API or language feature here so that you can get a `&dyn Trait` to a value without having to think about whether you need `&val` or `&&val`. So I opened an IRLO thread for that: [Smarter than `&&self.field` in derived debugs? - Rust Internals](https://internals.rust-lang.org/t/smarter-than-self-field-in-derived-debugs/20777?u=scottmcm)

---

<div class="post-metadata">

**Author:** ![system](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/system/32/51372_2.png) [@system](https://users.rust-lang.org/u/system)\
**Post date:** [August 4, 2024, 5:52pm UTC](https://users.rust-lang.org/t/why-it-is-not-allowed-to-cast-t-to-dyn-trait-where-t-trait-sized/110969/5 "2024-08-04T17:52:49Z")

</div>

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.
