New RFC for delegation: anyone interested in contributing?


#61

I’m not sure at all if this is the best place to discuss this, but I feel this is not worth a new thread: I made a highly tentative attempt at a pure trait/proc macro (no compiler modification required) approach: https://github.com/dureuill/delegate_test to delegate trait implementation to field.

Biggest drawback is that delegable traits must be marked as such. Also the implementation is very incomplete.

However I think this might give some directions for a “trait-based” delegation approach?

Please ignore if irrelevant.


#62

Biggest drawback is that delegable traits must be marked as such

That’s a pretty big drawback IMO. I imagine many use cases will involve delegating to traits in other crates, which may not have the trait marked as delegatable.


#63

Now that I gave it some thought, I think that nothing actually prevents me from generating the delegation trait for foreign traits, as long as the user copies pastes the definition of the foreign trait in the macro, and indicates to the macro where to find the foreign trait, and not to actually generate the trait. I’ll try and give it a try sometimes this week to see if this works in reality.


#64

That’s what I did for impl_sum. It uses an internal proc-macro to generate trait implementations for its delegating enums. It’s pretty horrible since it’s just an experimental crate, but it might give you some ideas.


#65

So… my scheme for foreign traits doesn’t seem to work. With local traits, I implement them in the following way:

impl<Proxy: delegate_LocalTrait> LocalTrait for Proxy {
/* generated implementation */
}

Which is fine since delegate_LocalTrait (generated by my macro) and LocalTrait are local.

But with a foreign trait this becomes:

impl<Proxy: delegate_ForeignTrait> ForeignTrait for Proxy {
/* generated implementation */
}

And this is where the orphan rules kick in: I would need to use Proxy as a type parameter for some local type, which is not what I want (or else I’ll have to use an intermediate struct on which the trait will be implemented).

Moreover, even without the orphan rules (I find it strange that they would apply since my generic parameter is constrained by delegate_ForeignTrait, which is a local trait), it doesn’t work for traits that already have “automatic implementation” (such as Into being implemented from From).

Implementation for foreign traits looks difficult.


#66

I think this is not the first attempt to use dedicated traits for delegation. This kind of attempt may bring some valuable insights but I consider it will always be somewhat unsatisfying as it does not satisfy a property that seems essential for delegation. I’d like to be sure we agree on this.

Let’s consider @zrk’s example. Outside of the delegation machinery where would anyone need a bound of the form where T: delegate_Work? My guess is nowhere. Trait consumers are interested in bounds for Work not for delegate_Work. However with a delegation system based on dedicated traits we would now be able to make the distinction between the types that directly implement Work and the ones that are leaving it to the delegation system. To me this is missing an important point: delegation should strictly be an implementation detail. The only persons that should be interested in delegating are the ones providing the implementations. External users are interested in the fact implementations exist or don’t, not in knowing how these implementations are actually defined internally. Delegation should then be completely invisible in the public scope.

Any solution that requires a trait representing the “capacity to delegate” is using an interface concept in order to reduce potential implementation boilerplate. This seems to me quite inappropriate.