Specifying that trait should be object-safe for purpose of casting to object

Well, I got a variation of this also working for you—AsObj is not generic on Trait here—but you could probably do that. The tricks are to

  1. implement AsObj for references to your traits/structs so that your Self is Sized, and
  2. implement AsObj for &Trait instead of requiring trait Trait: AsObj<Trait> which doesn't seem to be strictly necessary (conceptually, &Trait should always be coercible to &Trait without explicitly extending AsObj).

Playground
Edit 3: Playground Version with Obj<Trait> as well.

However, I haven't quite wrapped my mind around why the original error regarding Sized even happens. It's probably due to the same thing, but I oughta just go to bed now. :wink:

Edit: Aaaaah, I can't sleep because of this! I simplified the playground example above to really understand the Sized constraint, and it feels like a bug or shortcoming in the compiler. Here's the issue that lays out the bare minimum, but the devs may provide some insights as to the genericity of unsized types.

Edit 2: Failing to sleep even more, I recalled this thread where I learned about the as-yet unstable Unsize marker trait which serves the same purpose as your AsObj trait, allowing you to support both Sized types implementing &Trait and trait objects. Et voilà: playground.

Edit 3: Of course, in the morning, it aaaaaall makes sense now. Someone else pointed the same thing out on the issue as well. Trait objects consist of a pair of thin pointers—one to the vtable and one thin pointer to the object itself. Unfortunately, DSTs are fat pointers, so that when trying to convert, e.g., [Type] (fat pointer) to &Trait, you need the trait object to be a superfat pointer (at least 3-pointer-sized), which rust doesn't currently support. A special case is &Trait&Trait which doesn't need any conversion to a trait object as it's already one. Unsize<Trait> handles both the convertible cases (Type: Trait + Sized and &Trait).

1 Like