Pre-RFC: Unreserve inheritance-related keywords

At this point it seems pretty clear that Rust is not going to adopt inheritance as something built into the language. But still, it is currently impossible the use the following things as identifiers:

  • abstract
  • final
  • override
  • virtual

I was surprised by override in particular today, but would like to propose unreserving all four. I don't think this has been proposed before; the only RFC unreserving keywords that I am aware of was RFC 2421, which only touched on virtual and final in the Possible future unreservations section, and nobody talked about them in the comments either.

9 Likes

I believe the closest we've ever come to seriously proposing a feature closer to traditional inheritance is in the "delegation" discussions, but I'm not aware of any delegation proposal that ever proposed using one of these four keywords, and the current RFC proposes only adding new delegate and to keywords. So I have to agree the odds of us ever using these four are pretty much nil.

Plus, now that editions are a thing, we could re-add these later in the one in a million chance we'd ever want to.

6 Likes

I'd be in favor of unreserving these keywords, though if we do so, we should probably still try to "accept" them as positional keywords (in the positions someone might try to use them as inheritance keywords) for targeted diagnostics.

4 Likes

This looks good to me too.

To what use would these be put if they were unreserved? If used as normal identifiers, it would likely be confusing as these words have such specific meanings in most programming languages. Would they be used to make macros to allow for "Inheritance"? That might be OK, but, if they could also be used for any arbitrary thing, that could be confusing.

Besides the reason, "We don't know that we'll ever use these in the language," what's the motivation for unreserving them? It seems like there needs to be a case made beyond believing they'll never be used by the language.

9 Likes

I don't think we should have keywords on the basis of "it may be confusing in some situations". That is the job of lints, not keywords. So I am in favor of unreserving these keywords. We should be asking, why should we have these keywords, not why shouldn't we have these keywords, and if the answer isn't some concrete use in syntax (or some planned syntax is in the current or next edition), then we shouldn't have them as keywords.

That said, I agree with @gbutler that normal uses of these names would be confusing, so we could introduce a warn by default lint against using these names in definitions or declarations, probably in clippy?

8 Likes

Some examples:

let (abstract, contents) = read_paper();

let initial = initial_value();
let final = final_value();

let override = !item.keep_original();

They don't have to be related to the keywords' use in other languages.

For macro use, I don't think keyword-ness has any relevance, you could use keywords like other identifiers already as far as I know.

24 Likes

Seconded. For what it’s worth, I’m working on an application where exactly abstract in this context is extremely useful… and I only don’t use final a lot of times because it is reserved.

1 Like

You could always use Rust to implement object oriented dispatch for another PL (i.e. a compiler or virtual machine), in which case it'd be nice to have them available.

2 Likes

I hear where you're coming from, but, your usages there, to me, seem inappropriate in exactly the way I'd fear. For example, I would write "let initial ..." as either "let init ..." (if a small, local scope) or "let initval .." or "let init_value ..." (if a larger than a few lines local scope). Same for "final". For "let override ...", I'd prefer "let should_override ..." or "let should_override_item ..." or "let override_item ..." or "let override_it ..." (depending on the size of the scope involved).

Now, for "abstract", that one is a little less clear-cut to me, but, I'd still rather see something like, "let (paper_abstract, paper_contents) ..." or, if in a small scope, "let (p_abstract, p_contents) ..." instead for greater clarity, or, in a really small scope (like 2 or 3 lines) maybe, "let (ab,cont) = ..." (though, I wouldn't prefer that last at all, but, I'm OK with it for really small scopes.

In other words, what I'm saying, is having these keywords available for use as identifiers isn't really needed. Why have the churn of taking them out of reservation, only to possibly need to re-reserve them at some point. Are we 100% sure that Rust will never want to have layout/implementation inheritance?

I would agree making something a reserved word for that reason alone would be incorrect. However, not removing something from reservation that has been previously reserved should be justifiable with that reason alone without a strong case of need to unreserve (IMHO). That being said, there is the additional reason here, that, it is not a given that Rust will never want to add implementation/behavior inheritance as part of the language, and if it is ever wanted, it is very likely these keywords would be needed/desired. They are already reserved. They are reserved because they would be useful should Rust want to add that feature. There should have to be a good case to unreserve them (I would think).

I just don't see any need here to unreserve them. Shouldn't a "change" require a solid reason?

Is it really clear? Just because it isn't a priority, it doesn't seem clear that in won't become a priority at some point.

I'm not a fan of inheritance, but, unless one of the following is 100% true, I'm not sure how "clear" it is:

  • It is impossible to do inheritance in a "Sound" fashion (provably impossible) under Rusts memory model and ownership/borrowing rules
  • The language community and developers agree now that, for the reason that, inheritance isn't needed, desired, nor justified EVER, it will NEVER be implemented in the language and any RFC suggesting such addition to the language will be immediately rejected without discussions for that reason

If neither of those two things are the case, then, it seems not so "clear" to me.

EDIT: In other words, what I'm saying, is that any RFC/PR unreserving these keywords should establish one of the above points as part of the acceptance of such RFC/PR. If that bar cannot be leapt, then, they should remain reserved.

1 Like

These keywords were reserved before 1.0, and things have significantly changed since their reservation. The motivation for reservation being two, now closed RFCs for single inheritance, associated field inheritance. These two RFCs were closed and reworked into Efficient Code Reuse (which was also discussed here on internals, which lists a few other RFCs) (still prior to 1.0) because we wanted to ship 1.0, and these weren't important enough at the time.

In the end of the ECR internals thread, @nrc noted that

The favourite idea in the end has been a combination of leveraging specialisation and adding fields to traits. However, that is blocked on specialisation which is not yet stable and the feature as a whole is no longer considered high priority, so it won’t be in the 2018 edition (it is definitely still desirable, we just have a lot of higher priority things happening).

So I don't think that Rust will be seeing inheritance for at least 2 editions (which is aboout 6 years at our current pace). We'll be getting specialization probably by the next edition, so we can experiment with that, and see if we need anything more, and fields in traits doesn't need any of the keywords listed above, so I don't see the reason to keep them reserved.

To me, this is just old cruft we can dispose of. We don't have any active proposals for OO in Rust that I'm aware of (ECR RFC is more a list of goals than a), and all previous proposals were not accepted because we don't want OO in Rust.

5 Likes

You're welcome to have your own opinions on variable names, but keywords is a wholly inappropriate mechanism to enforce opinionated coding styles.

It's not needed. It's a nice-to-have. I think we all recognize that.

This is a good question, and I would encourage everyone in this thread to focus on questions like this rather than on opinionated coding styles.

17 Likes

I’ll bite from another angle: is it clear that the keywords are not going to be used for purposes other than Java-style OOP? Just for one example, I recall abstract being proposed as syntax for this feature:

4 Likes

The new syntax for existential types is type T = impl Trait;, but I see your point.

  • abstract - we could potentially use this for some other feature, but it may be a bit confusing coming from Java. It's also not that descriptive, so it's not a great keyword anyways.
  • final - sufficiently general that it could be applied elsewhere, I don't think we risk this being confusing
  • override - basically begs to be used in conjunction with inheritance
  • virtual - I don't know about this, the only features I can think of that would use virutal also overlap a lot with traits, so we don't need them. But this could just me being not imaginative enough
4 Likes

Perhaps a good argument for unreserving them now is that no one will be tempted to shoehorn one of these keywords into a feature that doesn’t really fit.

I’m looking at you, auto...

7 Likes

I'd like to use override as an identifier (specifically here) and don't think it would be confusing.

final and override could potentially have use in specialization, if it was redesigned.

8 Likes

final is definitely one I get burned by every so often, though not to the extent where I feel the need to use r#final... it's usually fine to rename as result. But it is a bit annoying given final isn't actually used anywhere.

1 Like