First of all: I apologize for taking so long to reply to you; I first wanted to clarify where I was going before answering your points, rather than hand-wave them, and it took much longer than I had anticipated.
Coercible
...
So, regarding all this talk of coercion, I actually plan to remove it altogether.
I used a generic term to describe a very specific relationship (parent-child) and on top of that there was indeed a conflation of uses: both a marker trait, and an implementation.
I will instead recommend using a specific vocabulary as part of the RFC.
#[parent]
There are undeniable advantages to using an attribute on an existing data-member, not the least of which is the easiness to refer to said data-member. Or of looking it up on Google (named entities are so much easier to look up than symbols).
On the other hand, it seems more "tacked-on" (why would traits be special-cased?) and expressing bounds is less obvious (whereas if you use Child: Parent
like trait, you expect Child: Parent
to be a valid bound syntax).
Ultimately, it is something I'll leave up to debate, and I'll mention the #[parent]
syntax in the alternative section of the RFC so that the community may decide.
This feels very nice, though I'm not completely clear on what would happen if multiple parents implemented the trait.
The compiler would simply refuse to automatically implement the offending methods, complaining about the ambiguity, and the user would have to specify them manually.
It would be better if the compiler could perform the up-casts implicitly, much like with Deref, there seems to be little point in having the user fiddling with as over and over.
This seemed really cool, until @cmr mentioned the potential issues in specifying the algorithm of what to deref to... I plan to strike this down and instead propose a lightweight (but explicit) syntax such as child as &Parent
. I'll let the author of Child
decides whether it's worth it to implement Deref<Target = Parent>
or not.
unsafe impl<T, S> Coerce<Box<DynClass<T, S>>> for Box<Class<T, S>> { }
For now I just moved to convert::From
. Works pretty well!
fn up_cast<T, S, B, P>(original: Box<DynClass<T, S>>) -> Box<DynClass<B, P>> where T: B, S: P, S: CoerceRef<P>;
Similarly, this could be done via Coerce
.
Actually, I moved on to specific [Up|Down]Cast[Ref|]<T>
traits, and simply provided an implementation of UpCast<Box<DynClass<B,P>>>
for Box<DynClass<T,S>>
.
Extend
My mistake, I read Trait: Extend<Struct>
in your RFC and mistakenly concluded that it meant the trait had fields, where it was in fact just a bound. I should have been more careful.
My general feeling is that I definitely like this proposal, probably in large part because of its similarity to the proposal I made. I think that focusing on having a set of features that do not step on each others' toes and work very well together is incredibly important, and I think you have done a good job at doing that.
I think so too! On the recommendation of @cmr I made a prototype you can find at GitHub - matthieu-m/rust-poly: Exploration of polymorphism in Rust and I'll now be re-working the RFC based on the experience I gained from it and the feedback I received from here.
I expect it to take me some time, but hopefully by the end of the week I'll have something I am not too ashamed to show off.
Thanks for your detailed feedback, and once again, my apologies for taking so long to answer.