I’m currently considering to write a new (and shorter) RFC for delegation in replacement of 1406 which was postponed.
Threads like this one or this other one showed that a certain number of people may want to contribute. Maybe some of you have already started drafts on their side. Could anyone interested please contact me?
This was already mentioned in the original RFC. Now the fact is blockers were far more “trivial” so while it can of course still be considered as an interesting extension for the future, I’m afraid it is clearly out of reach for the time being.
I’m strongly in favour of this moving ahead and I hope as many people get involved as possible. I have no doubt this will make it into Rust, but whether it happens this year, next year or in 10 years time depends on people volunteering time to make it happen.
Unfortunately, I have negative bandwidth at the moment, but I’ll help as much as I can whenever I get a moment. Thanks, @burakumin for continuing to push on this.
Easy/Ergnonmic delegation is something Rust should definitely have. To me, it is more important than inheritance, and, if we had proper ergonomic delegation, then inheritance wouldn’t be needed as all useful inheritance can effectively be modeled through delegation.
It would be nice to be able to delegate “Properties” as well. Would require some thought.
I have no time this week, but, I’d like to contribute to the development of this RFC.
Search for “TODO” if you’re not sure where to jump in. Everyone can edit the document from within their web browser, just sign in with GitHub and you’re off to the races!
Is it useful and/or feasible to allow delegation statements to appear anywhere in the impl block, rather than all at the top?
Is “contextual keyword” the right term and mechanism for delegate and to as proposed here?
Do we want to support all kinds of trait items, or should we be even more minimalist and support only methods in the first iteration?
Are there any possible extensions the proposed syntax is not forward compatible with?
How does delegation interact with specialization? There will be a default impl block in the future. Should we allow delegate to be used in a default impl block?
Syntactically, I prefer the previous presentation with use {whoever} for {whatever}, instead of delegate {whatever} to {whatever}. Also, I believe that writing self.field/Self::fun/Self::type instead of field/fun/type is 1/ more consistent with existing syntax; 2/ better suited for future extensions.
On the other hand, I agree that explicitly mentioning const, fn or type is clearer than the previous syntax.
I’ve published an RFC for inherent trait implementation. In the discussion of the previous RFC lang-team seen a close relation to the delegation. While I personally think that delegation and inherent traits have a different scope and can play nicely with each other, “delegating inherent impls” listed as one of the possible future extensions. What is opinion of those who works on delegation? Do you think it’s better to cover inherent traits in a new delegation RFC or do you think we better follow #[inherent] approach described in the RFC2375?
Please read the issues listed in the RFC for more context. Workarounds still present an inconvenient papercut for crate users, as they have to think about traits structure when they do not care about generics. Plus “just use glob imports almost everywhere” is a bad advice in my opinion.
I agree a list should be enclosed in brackets. In the name of readability, perhaps reword slightly to permit:
impl TR for S {
delegate to f {
fn foo,
fn bar,
const MAX,
type Item
};
}
I mention this to allow long lists of deferred items without hiding which field will be taking responsibility. That is probably the most important information, so should be highlighted earlier.
The extra context-keyword to seems unsightly though. Alternatives?
delegate(field) { fn method };
delegate field { fn method };
However this muddles the usage of * to denote all trait items.
Thanks @newpavlov, I haven't read through everything yet. Can you help me precisely define the issues here, so we know exactly what needs solving? I find it helps to focus the design process. e.g.
How do these workarounds present an inconvenient papercut for crate users?
In what cases do they have to think about traits structure when they do not care about generics?
Why is “use glob imports” bad advice? What issues does it cause?
I'd like to make this use case as easy as possible and having a concise problem statement to start with helps time-poor contributors get into it.
The argument for this syntax is "when trait items are explicitly listed rather than globbed, the line quickly becomes long and difficult to read." However, this can be solved by moving to field_name; to a new line, e.g.
impl TR for S {
delegate fn foo, fn bar, fn baz, const MAX, type Item, type Output
to really_long_field_name;
}
EDIT: We could make this a rule in rustfmt: when not delegating * move to field_name; to a new line. This would make it stand out visually.
impl TR for S {
delegate * to f;
fn foo(&self) -> u32 {
42
}
}
do we want to have something like “override” in other languages to indicate to the compiler we want to alter “delegation” here explicitly from what we’ve told by delegate * to f; with the semantic to not allow an “override” to elements not defined in f preventing typos etc.?
impl TR for S {
delegate * to f;
#[override(from="f")]
fn foo(&self) -> u32 {
42
}
}