Is it still possible to make progress on postponed features? The case of delegation

This recent thread made me think again about the status of delegation and wonder which kind of action (if any?) could unlock the current situation. Delegation has been proposed twice since 2015. Both finally been postponed. Here is Niko Matsakis's closing message from the last github discussion:

Hello everyone; we discussed this RFC in our backlog bonanza. The consensus was that we that we should postpone it, as we don't think we have the bandwidth to see to it right now, but we are very interested in this general direction, and we agree that this addresses some real problems in Rust. We would like to encourage folks to discuss it when the time comes for us to discuss our upcoming roadmap (one of the procedural changes we have in mind is to make it clearer when we'd be open to bigger proposals).

Emphasis is mine. How is the community supposed to know when the rust team is "open to bigger proposals" ? Proposing a third PR is definitely a no go right now as I don't see any reason why this new proposal would meet a different fate from its predecessors:

Speaking for the team, I do want to apologize. I realize that we encouraged @elahn and others to do this design work, and then let it languish and I'm sorry about that. :frowning:

So my question is simply: is there anything that can be done on this feature, and similarly on any postponed feature? Or should one just hope for any uncertain future announcement for the upcoming roadmap (whatever this means)?

20 Likes

My understanding is language feature RFCs will only be considered if proposed by a member of an official team or working group. So the process is:

  1. recruit a number of people interested in forming a working group to propose language feature(s);
  2. file an issue on the lang team repository proposing the new working group with an initial list of members;
  3. the lang-team decides if they're interested in liaising with and reviewing RFCs on this topic at this time.

At the start of 2019, my health significantly deteriorated and I have since been unable to organise a working group. I'd be happy to contribute to one when capable, but I can't commit any regular time/energy.

For this specific case, I'd suggest an Efficient Code Reuse Working Group. In my mind delegation is an excellent solution and I'd imagine such a working group producing a series of small RFCs proposing pieces of delegation.

The rationale for forward compatibility with future delegation RFCs, discussion and objection handling would occur on the working group repository, so only discussion related to the specific proposal would happen on the RFC thread, allaying lang-team members' fears of having to wade through long discussions continuously relitigating concerns.

6 Likes

To complement the above answer with a much smaller-scale one, more specific to delegation in particular...

While I've always been personally interested in delegation, and feel the problem is an important one to solve, I eventually became personally convinced that it wasn't worth any core language changes because:

  • every coherent version of "delegation" I'm aware of was a "pure sugar" feature, not enabling anything fundamentally unwritable today, but allowing certain kinds of code to be far more concise, readable and easily maintainble
  • as proc macros matured, we started seeing crates like ambassador - Rust with syntax that IMO is nearly as good as the best concrete delegation proposals I've seen (and IIUC can't be made much better, given all the information you must provide to disambiguate the delegation you want)
  • leaving this problem to crates allows much more freedom to experiment and evolve

(I haven't been participating in IRLO as much as I used to, so I have no sense of how many others feel similarly)

3 Likes

On the contrary, native delegation could allow for reuse of documentation and avoiding the need to restate the function header.

4 Likes

Actually, it looks like the current version of ambassador is doing some trickery (defining a macro_rules! with the name of the trait) because it doesn't require respecifying the method signatures. It only needs help with where clauses and generics on the trait.

Thanks for the detailed information. Can anyone in the language team confirm this is indeed the official process?

If this is a shared feeling I certainly intend to give up on this feature. It proved surprisingly difficult to make any advancement for what I thought was (and still think is) a straightforward sugar. But at least there had been a shared agreement on the legitimacy of having delegation as a language construct. If it is not even the case anymore, I certainly do not want to spend additional energy on trying to convince other people.

Ambassador is great, I applaud the author and I'll probably use it at some point, but it's still too much boilerplate for my regular use. When iterating on a design, going to every trait/struct definition and copy-pasting it is too much. Boats wrote:

without Ok wrapping, users need to 1 + N edits, for every happy path return in their function, every time they change whether this function returns a Result.

And I have a similar experience with manual delegation or when assisted by ambassador. In the end, I give up type safety for development speed - when my project grows to multiple developers, this will no longer be an option. From the ambassador docs:

If you want to make an existing trait that lives outside you crate available for delegation, you can do so by copy-pasting it's signature into your code and using the #[delegatable_trait_remote] attribute...

If you want to make an existing type that lives outside you crate delegate, you can do so by copy-pasting it's definition into your code and using the #[delegate_remote] attribute...

I most often want a newtype where all traits and inherent methods (which ambassador doesn't support) are delegated. Essentially my newtype is identical to the original, but they fail to unify in typecheck. With language support, codegen could use a single instance - a win for compilation time and wins for code size and i-cache when rustc/LLVM doesn't deduplicate.

Efficient code reuse is an ergonomics win, allowing type safety and composition without sacrificing development speed during design experimentation. Does it have to be delegation as previously proposed? No, so if anyone is interested in being part of such a working group, please don't be discouraged by comments that previous designs aren't considered worth language support by some.

3 Likes

Could you please provide a motivating real life example for this?

Sure, the first one that comes to mind is u64 IDs. I have several ID domains and using a different type prevents passing an ID from a different domain.

That sounds like the newtype pattern to me which does not address the question at hand. Specifically, Ids ought to be treated like opaque cookies and not like numbers. In other words, It makes no sense to me to delegate all the underlying functionality of u64 to ids. You wouldn't need to add ids to each other for example.

What is a real world use case where a clean design needs full delegation of underlying functionality? My claim is that there isn't such a clean design and if such delegation is done it is actually indicative of a design smell.

Don't be too discouraged. For literally any proposed feature there will be people here saying it's a bad idea; right now there's a thread where people are arguing against stabilizing a feature that was merged as an RFC five years ago. The good news is that that doesn't mean it's actually bad. The bad news is that good or bad, it's practically impossible to add new language features these days. When was the last time Rust added any new feature that hadn't already been on the backlog for many years? If you have both a ton of energy to devote to rallying people and an implementation, you might be able to spearhead a feature to land someday; otherwise, no.

2 Likes

#[derive(Default)] on enums went from a proposal to being stabilized in roughly a year (it'll hit stable on Thursday). Large proposals are the difficult ones — small ones can be done with relative ease.

1 Like

Ids need not be opaque, e.g. sequential event Ids that double as a logical timestamp, so having Ord, being able to answer questions like what's the Id of the previous/following event are useful. I also use a more complex Id type from another crate, for multiple domains and use Eq, serialisation, generation, string encoding/decoding, etc.

I'm happy to work with others to produce convincing RFCs, but I've no interest in trying to convince anyone who hasn't felt the lack of efficient code reuse to participate in that process.

Yeah, a single person trying to get a nontrivial language feature over the line seems bonkers to me. However, with a working group to share the load and life getting in the way of one person not sinking the whole effort, then it's viable. :slightly_smiling_face:

Can someone from the language team confirm this? If yes, could this made into an official policy?

It seems improper to invite the community to contribute RFCs, if they are going to be rejected because of their provenance.

(I am not on the lang team.)

Saying an RFC will only be considered if proposed by a team member or wg is overly restrictive. Small, well-scoped RFCs can and do get considered and potentially accepted even when proposed by community members with little to no prior contributions to the project. (Though perhaps these are moving more towards being MCPs (compiler) and ACPs (libs) rather than "full" RFCs?)

For a language RFC change, though, it is true that a team member sponsor/liaison/mentor/etc is hugely beneficial. The project already has a large backlog of features (accepted RFCs and other language improvements) that still need both design and implementation work. These will quite reasonably get priority over adding more to the RFC-accepted pile. But even without that, language features especially have subtle implications on the language, both as currently implemented and to future planned developments. Ensuring that everything fits together is far beyond the reasonable ability of any individual, so having many eyes on a proposal as it gets drafted, including ones with experience with the relevant areas, is key to getting a proposal that is coherent to the design of the rest of the language.

So no, a working group isn't strictly required. But it is probably the best way to develop a proposal such that it actually covers everything that it needs to in order to be considered for inclusion in the language. Additionally, the charter of a wg is a good indicator that this is something that the relevant teams are in fact interested in solving.

(And I'll let you in on an open secret: most wgs are driven by the work of one or two people, with the others offering intermittent review moreso than any development. Or maybe I'm only exposed to the small ones where this is the case.)

Would it be better if the process were more clearly documented and transparent to a casual observer? Almost certainly! The C and C++ language processes has done an infamous job of driving away young and eager paper authors with an opaque process almost in retrospect designed to give false hope. Rust's process has a better track record, but it's still unfortunately got a similar undertone of false hope ("anyone can submit an RFC!") compared to the realities of what it takes to drive a proposal through that an in-group knows about, typically by having survived through it without self selecting out of the process.

Everyone is trying to make the process better, but it's not an easy task. And as the language matures, the bar for new inclusions necessarily gets pushed higher.

7 Likes

This is emphatically not the case. Anyone can make a language proposal.

For new proposals, you do need a language team member to be willing to support your proposal as a liaison (which we do in part to make sure that you'll have reviewers and that we'll have bandwidth), but anyone can make a proposal.

All that said, given the amount of work required to successfully get a non-trivial language proposal over the finish line (even with our new processes that are intended to be more approachable), if you don't start out being a member of the Rust project when you first propose one, don't be surprised if you end up as one by the time you're done. I can vouch for that path myself. :grinning:

1 Like

A poll to get an idea of the possible opinions

  • I would be interested in championing a new "Efficient Code Reuse" Working Group.
  • I would be interested in contributing to a new "Efficient Code Reuse" Working Group.
  • I think a new RFC for adding delegation as a language construct should be enough.
  • I think libraries like ambassador are good enough for supporting delegation.
  • I don't think delegation is a good idea to begin with.

0 voters

To iterate on @CAD97's comment, as the author of the first PR, my personal feeling is that the most discouraging aspect has not necessarly been the amount of effort to make in order to convince other people or to reach some form of agreement (though it definitely did require energy). It's the fact it was unclear if the effort was made on the appropriate place, if any advancement was made at all and if the other contributors and I were missing a key part of the expected process. If I were told that making progress on any proposal for Rust involves dancing naked for God Ferris every high tide, at least I would know what are the expectations and be able to decide if I'm ready and able to do it or not.

1 Like