Wrapping my mind around Coerce/CoerceUnized and DSTs


What does it mean when T: Coerce<ExampleTrait1>? I understand it’s a marker trait for trait impl blocks but does that open up fn func(t: T) { ... t as ExampleTrait1 .. } static casts inside a generic function (perhaps even getting around type parameter/concrete type mismatch errors?) or does it have to be t as dyn ExampleTrait1 with T: CoerceUnsized<ExampleTrait1>? If the latter, what prevents Rust from allowing generics to abstract over both scenarios if dyn Trait vtables follow the same format? Is the vtable guarantee even the same thing when you have something like T: CoerceUnsized<ExampleTrait<'lifetime, U>> or do all lifetime parametrized types point to the same implementation?

If I accept generic parameters I: ?Sized, T: Coerce<I>, F: Fn(I), can I then just call f(T as I) or would this require GATs as in something like trait Example<I> { type U<I>: Fn(T) where T: Coerce<I>; }? Would Chalk even be able to solve that requirement or would it punt it because there are potentially infinite conflicting implementations? In cases of infinitely recursive traits and associated types, why can’t Rust resolve the chain at the call site when a terminating type is known?

When is it appropriate to use Coerce/CoerceUnsized and what are the bare minimum guarantees I can get from the compiler (afaict, at the very least you need the same version of compiler for all relevant binaries)?

What is the state of custom DSTs? I haven’t seen any mention of them in a while.

For context: I’m working on a Webrender-based GUI framework that uses Frunk hlists, proc macros, specialization, and uninhabited types to allow a complex but ergonomic combination of OOP*-like* inheritance with trait based composition using unknown user provided types. While I’ve been able to implement ReactiveExtension-like combinators for events and inheritance of non-generic traits through heterogeneous lists, formalizing the rules of the type system in my mind has been a difficult process. I also recently experimented with using Windows PDB files generated by rustc to enable remote debugging of production deployments (for any type instrumented by a few reflection traits) so I’m curious about the guarantees provided by the unstable trait marker APIs.

I apologize if most of this can be answered just by “try it out on Rust playground” or “wait for GATs/Chalk” but I’ve been trying to process type level recursion’s failure modes so my brain is a bit stuck in that bubble.