# Problems with "dyn\* Trait"

**URL:** <https://internals.rust-lang.org/t/problems-with-dyn-trait/16420>\
**Category:** language design\
**Created:** [April 4, 2022, 10:42am UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420 "2022-04-04T10:42:16Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [April 4, 2022, 10:42am UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/1 "2022-04-04T10:42:16Z")

</div>

(NOT A CONTRIBUTION)

I read @nikomatsakis's post about "dyn\* Trait" and I wanted to share some problems with this idea. I feel like we discussed something very similar several years ago, so I was surprised to see this post without trying to address these problems, which I remember were brought up then.

> - `&dyn Trait` , for example, would become `dyn* Trait + ‘_`

This is the big problem with this proposal. Given a trait object `&dyn Trait` or `&mut dyn Trait` there are _two_ operant lifetimes, which have different implications for the moves and borrows that are allowed for this type. In particular, if you have `&'a mut dyn Trait + 'b`, you are covariant in `'a` and invariant in `'b`. It is also important because you may need to constrain other lifetimes in your signature to be the same as either `'a` or `'b`, but obviously not both (those other lifetimes could be invariant also, for example: `fn(&'b mut Type<'a>, &'c dyn Trait + 'a)`.

This means that given the signature of a trait object which is a reference, you need to be able to specify the reference lifetime separately from the lifetime of the trait object, and that reference needs to specify whether its mutable or not. This muddling with "trait views" (which seems like just more complexity to patch over the weaknesses of this proposal) doesn't solve the problem.

Let's say the final syntax does somehow have all of these knobs, but instead of composing reference types with an unsized trait object type (what we have now) you've got 3 (ref, mut ref, by value) new types with syntax for separately specifying these lifetimes (the by value one doesn't need it). How do they implement deref? What is the target type? And if they don't implement Deref, how do you Pin them, or use any other abstraction built on top of Deref?

As far as I can tell they would have to deref targeting the _old_ dyn Trait types. So you aren't even getting rid of that type. You'll have to have both systems forever. You can't just shift over at an edition boundary.

The new types would have these two advantages, as far as I can tell:

- You can pack objects that are less than a word in size into the pointer type.
- You can pass self by-value as an argument and return type, thereby making more traits dyn safe.

I'm not very hyped about the first point, but I think the second of these is a very intriguing goal. I want to note that people already do create "trait objects" that implement dyn unsafe traits and so forth - they do so using Any downcasting or a special clone method they make implementers provide or the erased\_serde bridge trait trick. People also do all kinds of representational tricks with their custom trait objects (anyhow using a thin pointer for example), and certainly can do small object optimisations like this if they really want to.

The problem that I see is that these things have to be done bespoke each time you want to do them, and that requires advanced understanding of unsafe code and the trait system and possibly exploitation of currently underspecified behavior. So rather than bake some aspects of them into a new type, I would ask: why aren't the tricks people do to create custom trait objects _libraries_ that anyone can pull down and compose with their own trait? What abstractions would be needed to make that possible? I'm not sure there's an answer, but to me this seems like a more compelling avenue to find parsimonious additions to the language to support these use cases.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [April 4, 2022, 10:49am UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/2 "2022-04-04T10:49:51Z")

</div>

What does “NOT A CONTRIBUTION” mean?

Also, perhaps consider including a link to the post you're discussing here?

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [April 4, 2022, 10:53am UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/3 "2022-04-04T10:53:51Z")

</div>

(NOT A CONTRIBUTION)

> [@steffahn](#):
>
> What does “NOT A CONTRIBUTION” mean?

Required by my employer. Here is Niko's blog post: [dyn\*: can we make dyn sized? · baby steps](https://smallcultfollowing.com/babysteps//blog/2022/03/29/dyn-can-we-make-dyn-sized/)

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [April 4, 2022, 1:40pm UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/4 "2022-04-04T13:40:38Z")

</div>

Not a problem, but an alternative direction we can take here.

We can make `dyn Trait` a sized type:

- allow various owning pointers [of certain layout] to be coerced to an owned `dyn Trait` type
- this notion can be extended to allow arbitrary unsized types, so that `[T]` type is sized, an actual storage is determined at creation site.

This overlaps the unsized values RFC (meaning of `let a: dyn Trait = ...` would differ) I think of introducing a kind of explicit `alloca`\* function in `std::mem` solving the following:

- `alloca` is not always avaliable - tie this to an std on different platforms
- it would be forbidden to use in async contexts with clear error messages (yet it can reside in plain function called by an async... not a problem\*\*)
- justifying current special case of unsized locals made from `Box` es.

This way, the only places we deal with `?Sized` types are data structure decalarations and storage for these.

\* `fn alloca<T: ?Sized>(val: T) -> Unique<T>` - allocate a memory and place a value on the current stack frame.   
A value given to the function is passed by pointer, the function allocates a memory using an alloca, writes the value into allocated value, and returns a value by pointer.   
This function is, in fact, compiler provided, and is `#[inline(always)]`.  
This goes into a separate `#[feature]`

\*\* if a futures need to store only the state crossing the `await` (yield for generators) point and given there's not way data of functions that a future calls inbetween `yields` is captured by the future, no memory allocated by `alloca` would ever **be in scope** of future\generator and thus there is no way it could be needed to store it in state.

Edit: `alloca` side note.

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [April 4, 2022, 4:14pm UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/5 "2022-04-04T16:14:11Z")

</div>

How does this differ from the unsized rvalues RFC? It seems pretty much the same to me. And how does it solve that RFC's problems, like `alloca`s in loops and returning unsized values?

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [April 4, 2022, 5:58pm UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/6 "2022-04-04T17:58:16Z")

</div>

My proposal is to make `alloca` an explicit operation performed by a special function.

This doesn't support returning unsized values with `alloca` at all. Instead, some implicit coercions of `Box` and likes to a value carrying an owning pointer + vtable with `drop` fn. ptr, as it is described in `dyn*` niko's blog post.

The two motivation points from unsized locals RFC were:

1. to support passing unsized values to functions;
2. to support allocating objects on stack in performance sensitive cases;

To support the 1 case we do explicit alloca for dynamic data, take a pointer to this data, and construct a `dyn*` object (which I really hope could be generalized to support also `[T]`, etc):

```rust
let data: Box<dyn Trait> = ...;
let alloca = std::mem::alloca(*data); // `*data` is a `dyn*` trait object
//here, alloca reside on the stack, yet it has been created from trait object, and it also has a `dyn* Trait` type

```

_In fact, I belive it'd be better if we changed the meaning of `dyn` to mean what is `dyn*` means._

Second motivation point is handled by `std::mem::alloca` (which I'm also proposing) function alone.

TODO: figure out this as `self` type

---

<div class="post-metadata">

**Author:** ![rpjohnst](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rpjohnst/32/9524_2.png) [@rpjohnst](https://internals.rust-lang.org/u/rpjohnst)\
**Post date:** [April 4, 2022, 7:38pm UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/7 "2022-04-04T19:38:54Z")

</div>

> [@withoutboats](#):
>
> So rather than bake some aspects of them into a new type, I would ask: why aren't the tricks people do to create custom trait objects _libraries_ that anyone can pull down and compose with their own trait? What abstractions would be needed to make that possible? I'm not sure there's an answer, but to me this seems like a more compelling avenue to find parsimonious additions to the language to support these use cases.

I had a similar thought, with a very rough sketch of one possible such abstraction: [Reddit - Dive into anything](https://www.reddit.com/r/rust/comments/tqwn4b/dyn_can_we_make_dyn_sized/i2lp687/)

That is, one way to look at this is that `dyn*` is folding the pointer type (which may be "no pointer") back behind the dynamic dispatch, to get a sort of pointer type polymorphism. This is what makes more traits `dyn*` safe- it lets you pick a strategy for passing and returning `Self` and associated types at construction time.

So rather than hanging this functionality off of `dyn`, we might introduce a new pointer-like type to compose with `dyn` (but also usable for other purposes- that's mainly where my Reddit post goes). This type would have to expose the intersection of the APIs of the pointer types it supports: Sized, a lifetime parameter, Deref, !Copy, drop glue, etc.

I'm not really sure either how much of this would need to go into the language vs libraries, but it feels like a useful starting point that's narrower in scope than "custom DSTs."

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [April 4, 2022, 9:21pm UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/8 "2022-04-04T21:21:47Z")

</div>

I have another concern with this proposal: "pointer-sized" is not clearly defined at type-checking time.

Is `Box<T>` pointer-sized? Sure. But `Box<T>` is actually `Box<T, Global>`, and so it's pointer-sized only because `Global` is a ZST. What with custom allocators? And even if we decide that we special-case `Box`, we still have to deal with _generic_ allocators (I expect a lot of ICEs to be caused by this). And what with other types? This seems to open the door to more post-monomorphization errors, a la `generic_const_exprs`. I _really_ don't like that.

---

<div class="post-metadata">

**Author:** ![quinedot](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/quinedot/32/7294_2.png) [@quinedot](https://internals.rust-lang.org/u/quinedot)\
**Post date:** [April 5, 2022, 12:30am UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/9 "2022-04-05T00:30:00Z")

</div>

Most of this comment is just nits.

> [@Blog](#):
>
> In Rust today, the type `dyn Trait` is guaranteed to implement the trait `Trait` , so long as `Trait` is dyn safe.

Probably irrelevant to this topic, but [this has never been true.](https://github.com/rust-lang/rust/issues/88904)

> [@Blog](#):
>
> `Box<dyn Trait>` would become `dyn* Trait` (note that a `’static` bound is implied today; this might be worth reconsidering, but that’s a separate question).

`Box<dyn Trait>` bounds are more nuanced than that.

- [The lifetime is inferred within a function body](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1b45e211571a10d4ea1b43d0429a5a3d)
  - [RFC 1156](https://rust-lang.github.io/rfcs/1156-adjust-default-object-bounds.html#detailed-design)

- [The lifetime is bound in generic structs with an explicit bound](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=cec021365a805ddc31862f6ae3b6f017)
  - [RFC 2093](https://rust-lang.github.io/rfcs/2093-infer-outlives.html#trait-object-lifetime-defaults) (maintaining the RFC 1156 rule for this case)

> [@withoutboats](#):
>
> In particular, if you have `&'a mut dyn Trait + 'b` , you are covariant in `'a` and invariant in `'b` .

While true from a subtype perspective, [`Unsize` coercion can make `'b` act covariantly (search for "Interaction with object coercion").](https://rust-lang.github.io/rfcs/0599-default-object-bound.html#detailed-design)\[1\] This doesn't matter when the lifetimes are intertwined with others in the signature, as you note.

> [@tema2](#):
>
> Not a problem, but an alternative direction we can take here. We can make `dyn Trait` a sized type:
> 
> - allow various owning pointers [of certain layout] to be coerced to an owned `dyn Trait` type
> - this notion can be extended to allow arbitrary unsized types, so that `[T]` type is sized, an actual storage is determined at creation site.

How would that be phased in considering [these currently-non-overlapping implementations?](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=938473032b9801b943785b54df37435d)

```rust
impl<T /* : Sized */> Trait for [T] {}
impl<T /* : Sized */> Trait for T {}
impl Trait for dyn Display {}

```

* * *

1. [And maybe the coercion makes the subtype distinction meaningless.](https://users.rust-lang.org/t/solved-variance-of-dyn-trait-a/39733/14)

---

<div class="post-metadata">

**Author:** ![beepster](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/beepster/32/7914_2.png) [@beepster](https://internals.rust-lang.org/u/beepster)\
**Post date:** [April 5, 2022, 4:41am UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/10 "2022-04-05T04:41:50Z")

</div>

> [@chrefr](#):
>
> And even if we decide that we special-case `Box`,

Please no, the last thing Box needs is _more_ magic.

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [April 5, 2022, 11:23am UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/11 "2022-04-05T11:23:53Z")

</div>

> [@quinedot](#):
>
> How would that be phased in considering [these currently-non-overlapping implementations?](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=938473032b9801b943785b54df37435d)
> 
> ```rust
> impl<T /* : Sized */> Trait for [T] {}
> impl<T /* : Sized */> Trait for T {}
> impl Trait for dyn Display {}
> 
> ```

Making `dyn Trait` a sized type renders `impl Trait for dyn Trait` useless, since the notion of `dyn` is changed.   
While no easy answer, I think here we should just use specialization rules extended to say smth. like "`impl Trait for dyn Trait` type is even more general than `impl<T> Trait for T`". This way we gonna use methods from impl if we basically have no other impl in existence.  
Also, involvement of an impl for `dyn Trait` require implicit unsizing of a concrete type (so the method resolution can make code from `impl Trait dyn Trait` to work), which we don't want at all, I guess.   
Alternative is to make such impls do nothing, as bounds in generics type aliases currently do.

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [April 5, 2022, 11:58am UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/12 "2022-04-05T11:58:16Z")

</div>

> [@tema2](#):
>
> we should just use specialization rules

Wouldn't this mean this feature would be blocked until a sound specialization design is found?

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [April 5, 2022, 12:12pm UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/13 "2022-04-05T12:12:37Z")

</div>

Actually, yes. The problems arise when chosing between `impl<'a> Trait for dyn Trait + 'a` and `impl Trait for dyn Trait (+ 'static)` (is that 'static bound implied when no other one is specified?).

And after that I'm in strong favor of not searching for methods in `impl Trait for dyn Trait`:

- first, it avoids conflicts from [here (this topic)](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/9).
- second, it allows to auto generate impls of `Trait for dyn Trait`, because the latter is now actually an owning pointer to a DST value.

But such transition also require an edition.

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [April 5, 2022, 2:11pm UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/14 "2022-04-05T14:11:28Z")

</div>

> [@tema2](#):
>
> not searching for methods in `impl Trait for dyn Trait`

What about associated types though?

```rust
trait Foo {
    type Bar;
}

impl<T> Foo for T {
    type Bar = ();
}

trait Baz {}
impl Foo for dyn Baz {
    type Bar = i32;
}

fn test<T>(_bar: <T as Foo>::Bar) {
    let _bar: () = _bar;
}

fn oops() {
    // <dyn Baz as Foo>::Bar == i32, but this is not what `test` expects
    test::<dyn Baz>(0i32);
}

```

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [April 5, 2022, 2:25pm UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/15 "2022-04-05T14:25:00Z")

</div>

> [@SkiFire13](#):
>
> ```rust
> trait Foo {
> type Bar;
> }
> //first
> impl<T> Foo for T {
> type Bar = ();
> }
> ...
> trait Baz {}
> //second
> impl Foo for dyn Baz {
> type Bar = i32;
> }
> 
> ```

This is unsound usage of specialization (from generic impl (first), to concrete one(second)).  
Associated types shouldn't be specializable, because even if we make some kind of sanitization mechanism, this'd still be introducing too much action-at-a-distance problems in codebases.

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [April 5, 2022, 3:40pm UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/16 "2022-04-05T15:40:58Z")

</div>

> [@tema2](#):
>
> But such transition also require an edition.

As a hack in sake of backward compatibility, we can make impls of shape `impl Trait for dyn Trait {}` to not consider `dyn Trait` sized =). Given impls of more complex shape (such as `impl Tr for (u8,dyn Tr)`) are probably very rare, so a crater run will judge.

And then we can make `dyn Trait` a `Sized` type, so that:

```rust
struct S(u8,dyn Trait); //becomes Sized
//struct S(u8,[u8]); //can also become Sized, given this mechanism extended to slices.

fn f(a: dyn Trait); //no loger requires `unsized_locals` feature
fn f() -> dyn Trait; //becomes possible (but not zero-cost) to make this work, function `f` should itself allocate an object, and coerce it

```

Are there any ways to do dispatch on whether a type is `Sized` or not?

---

<div class="post-metadata">

**Author:** ![lordan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/lordan/32/2107_2.png) [@lordan](https://internals.rust-lang.org/u/lordan)\
**Post date:** [April 7, 2022, 12:44pm UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/17 "2022-04-07T12:44:12Z")

</div>

For my own edification: is `dyn* Trait` essentially equivalent to the canonical C++ object layout (i.e., a vtable ptr prepended to the actual object), with an upper bound on object size? Or am I misunderstanding the proposal?

---

<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:** [April 7, 2022, 12:59pm UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/18 "2022-04-07T12:59:39Z")

</div>

`dyn* Trait` would still be two pointers big, `(ptr, &vtable)`. The difference with `&dyn Trait` is that it owns the pointee ("`&move`") and that it also can inline pointer sized values with a special vtable.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [April 7, 2022, 6:10pm UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/19 "2022-04-07T18:10:57Z")

</div>

(NOT A CONTRIBUTION)

> [@CAD97](#):
>
> `dyn* Trait` would still be two pointers big, `(ptr, &vtable)` . The difference with `&dyn Trait` is that it owns the pointee (" `&move` ") and that it also can inline pointer sized values with a special vtable.

I don't believe its intended that this type owns the pointee necessarily - Niko refers to `&dyn Debug` as being `dyn* Debug + '_`. Presumably it only owns the pointee if its static. This means though that you can't have the equivalent of `Box<dyn Debug + 'a>`. Its unclear how the distinction between a copiable and not copiable (`&` vs `&mut`) trait object reference was supposed to be made though, possibly it was that `dyn* &Debug + '_` was copiable whereas `dyn* Debug + '_` was not. Niko would have to say.

And this isn't even getting into things like `Arc<dyn Foo>`. These are just more good reasons why the composition between the pointer type and the trait object type makes a ton of sense.

---

<div class="post-metadata">

**Author:** ![yaahc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/yaahc/32/6606_2.png) [@yaahc](https://internals.rust-lang.org/u/yaahc)\
**Post date:** [April 7, 2022, 9:08pm UTC](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420/20 "2022-04-07T21:08:03Z")

</div>

> [@withoutboats](#):
>
> I'm not very hyped about the first point, but I think the second of these is a very intriguing goal. I want to note that people already do create "trait objects" that implement dyn unsafe traits and so forth - they do so using Any downcasting or a special clone method they make implementers provide or the erased\_serde bridge trait trick. People also do all kinds of representational tricks with their custom trait objects (anyhow using a thin pointer for example), and certainly can do small object optimisations like this if they really want to.

I am not familiar with the "bridge trait trick" you're referencing in `erased_serde` and want to check it out, but we have been working on abstractions for some of the patterns you described

- [Add new ThinBox type for 1 stack pointer wide heap allocated trait objects by yaahc · Pull Request #90066 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/pull/90066)
- [https://github.com/rust-lang/rust/pull/91970](https://github.com/rust-lang/rust/pull/91970)

The first one is a generalized implementation of the thin pointer logic from `anyhow`. The second one is an abstraction similar to `Any` for passing arbitrary types out of trait objects which lets you provide generic wrapper methods on trait objects like `fn get_context<T>(&dyn Error) -> Option<T>` getter we're looking to add to `Error`. When I poked around for a minute inside of `erased_serde` I saw a mention of another related `typetag` library, and I'm very curious to know if there's any similarities between that API and the typetags that underpin the `Provider` API: [Add the Provider api to core::any by nrc · Pull Request #91970 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/pull/91970/files#diff-0752889661748b8a15a597d7156127b6fb90fdeda0627be50e07f3f785bd0f4dR805)

[Next page](https://internals.rust-lang.org/t/problems-with-dyn-trait/16420.md?page=2)
