# \[Idea\] Fully Dynamic Trait Object

**URL:** <https://internals.rust-lang.org/t/idea-fully-dynamic-trait-object/10636>\
**Category:** language design\
**Created:** [July 28, 2019, 12:29pm UTC](https://internals.rust-lang.org/t/idea-fully-dynamic-trait-object/10636 "2019-07-28T12:29:14Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![crlf0710](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/crlf0710/32/1987_2.png) [@crlf0710](https://internals.rust-lang.org/u/crlf0710)\
**Post date:** [July 28, 2019, 12:29pm UTC](https://internals.rust-lang.org/t/idea-fully-dynamic-trait-object/10636/1 "2019-07-28T12:29:14Z")

</div>

I'm reading some ECMA-335 text today, which is about the design of dotnet CLI. There's something called typed reference there, which consist of static data type and the address of data, which reminds me of the trait objects in rust.

So, in rust, one way to think about the trait objects is: it's actually a more generic type constrained by const generics, taking some metadata matching a trait as the constant, and the resulting type automatically implements the trait.

And by removing the constant bound, maybe there can be a `dynany` type. Its relationship to `dyn Trait` is just like `&[T]` to `&[T; 3]`. Using a `AsRef/AsMut`, the Trait part of `&dyn Trait` can be erased, transformed into a `&dynany` type, and by specifying the metadata for some trait as constant generics, `&dynany` can `TryInto` some `&dyn Trait`.

In this idea, `Box<dynany>` can supply uniform storage for every value, and `&dynany` can supply uniform storage for shared pointers.

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [July 28, 2019, 2:12pm UTC](https://internals.rust-lang.org/t/idea-fully-dynamic-trait-object/10636/2 "2019-07-28T14:12:30Z")

</div>

Like [`std::any::Any`](https://doc.rust-lang.org/nightly/std/any/trait.Any.html)

---

<div class="post-metadata">

**Author:** ![H2CO3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/h2co3/32/2849_2.png) [@H2CO3](https://internals.rust-lang.org/u/H2CO3)\
**Post date:** [July 28, 2019, 2:20pm UTC](https://internals.rust-lang.org/t/idea-fully-dynamic-trait-object/10636/3 "2019-07-28T14:20:17Z")

</div>

Yeah, sounds exactly like `Any` to me.

(Side note: its usefulness/necessity is much more limited in Rust. I have no idea about how idiomatic/widespread/useful/necessary it is on the CLR, but usually in Rust it certainly is/should be a last resort solution, unlike strongly-typed existentials.)

---

<div class="post-metadata">

**Author:** ![crlf0710](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/crlf0710/32/1987_2.png) [@crlf0710](https://internals.rust-lang.org/u/crlf0710)\
**Post date:** [July 28, 2019, 4:04pm UTC](https://internals.rust-lang.org/t/idea-fully-dynamic-trait-object/10636/4 "2019-07-28T16:04:42Z")

</div>

But `Any` is flawed, almost useless in its current state. You can't turn another trait object directly into `&dyn Any`, nor try to turn it back.

Whenever you want to use it, something like `Object` in [https://docs.rs/query\_interface/](https://docs.rs/query_interface/) will be more useful.

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [July 28, 2019, 4:52pm UTC](https://internals.rust-lang.org/t/idea-fully-dynamic-trait-object/10636/5 "2019-07-28T16:52:26Z")

</div>

You can turn another trait into the one you want if you use a simple extension trait.

```rust
trait ExtWithAny: FooTrait + Any {
    fn as_any(&self) -> &dyn Any;

    fn as_base(&self) -> &dyn FooTrait;
}

impl<T: FooTrait + Any> ExtWithAny for T {
    fn as_any(&self) -> &dyn Any { self }

    fn as_base(&self) -> &dyn FooTrait { self }
}

```

You can add other methods to this to convert between other pointer types. There's even a crate that does this for you, if only I could remember its name.

Then you use this extension trait instead of the bae trait, and everything works out.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [July 28, 2019, 9:54pm UTC](https://internals.rust-lang.org/t/idea-fully-dynamic-trait-object/10636/6 "2019-07-28T21:54:18Z")

</div>

A few related crates:

- [downcast](https://crates.io/crates/downcast)
- [downcast-rs](https://crates.io/crates/downcast-rs)
- [dynamic](https://crates.io/crates/dynamic)
- [mopa](https://crates.io/crates/mopa)

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [October 26, 2019, 9:58pm UTC](https://internals.rust-lang.org/t/idea-fully-dynamic-trait-object/10636/7 "2019-10-26T21:58:36Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
