I'm trying to understand how trait objects convert to and from raw pointers.
If I try to convert a trait-typed reference to a raw pointer, I get E0495, which complains about lifetimes without reference to the vtable. If I use a struct-typed reference instead, it works, which suggests that the problem is indeed related to the vtable pointer even though the compiler error doesn't say so.
What does this mean exactly? How did you try this?
Trait objects use a fat ptr - it’s essentially a (usize, usize) pair where the first ptr is to the data and the second to the vtbl. A raw trait object ptr is the same thing.
I think your errors are not related to the vtable but really to lifetimes. If you write trait Decoder : 'static { ... } (ruling out e.g. decoders containing stack pointers), then the errors disappear.
Note that the Decoder in &'a Decoder is more restrictive than the one in *mut Decoder. Regarding the actual type T of the object (which implements Decoder), the former requires that it outlives 'a but the latter requires that it outlives everything. Your error seems to disappear when you change the return type:
It probably should issue a warning, or perhaps clippy is the right place for that. Technically, C code can decompose it into the 2 parts and store it as context - then pass it back somewhere else to Rust. Trait object repr isn’t guaranteed however, and so that’s why there probably should be a lint against it.
The ABI is unstable but current impl is known - it’s a fat ptr. The fat ptr is two usize values, the first being a ptr to the data (ie the starting memory address where the value resides) and the second being a ptr to the vtbl. So the C side could be a struct with two *void ptrs, which is basically https://doc.rust-lang.org/std/raw/struct.TraitObject.html.