# \[Pre-RFC\] Inheritance

**URL:** <https://internals.rust-lang.org/t/pre-rfc-inheritance/4888>\
**Category:** language design\
**Created:** [March 1, 2017, 10:05pm UTC](https://internals.rust-lang.org/t/pre-rfc-inheritance/4888 "2017-03-01T22:05:09Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![dobenour](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dobenour/32/7241_2.png) [@dobenour](https://internals.rust-lang.org/u/dobenour)\
**Post date:** [March 1, 2017, 10:05pm UTC](https://internals.rust-lang.org/t/pre-rfc-inheritance/4888/1 "2017-03-01T22:05:09Z")

</div>

This is a pre-RFC for inheritance.

# Motivation

Use cases include GUIs and certain tree-like structures (ex. Servo’s DOM). In both cases, interfaces allow the type system to guarantee what it would otherwise not be able to. Servo is currently forced to use unsafe code to work around this.

# Detailed design

## Syntax

A class is declared as follows:

```rust
struct class X {
    ...
}
// OR
enum class X
    ...
}

// Here's how you extend another class
struct class Y : X {
    ...
}
// Same for enum-based classes
enum class Y : X {
    ...
}

```

The contextual keyword `class` is added. It is valid only after the keyword `struct` or `enum`.

Only single inheritance is supported. Methods of a class can be declared virtual by placing the `virtual` contextual keyword before `fn`. To override a method, the `override` contextual keyword must be used in the same place.

## Typing

Classes do not implement `Sized`. Therefore, only references can be used. A subclass reference can be cast to a superclass reference using the `upcast` method or the (new) `:>` operator.

In general, type inference in the presence of subtyping is difficult, so upcasting is not implicit.

---

<div class="post-metadata">

**Author:** ![ExpHP](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/exphp/32/6208_2.png) [@ExpHP](https://internals.rust-lang.org/u/ExpHP)\
**Post date:** [March 1, 2017, 10:47pm UTC](https://internals.rust-lang.org/t/pre-rfc-inheritance/4888/2 "2017-03-01T22:47:14Z")

</div>

_What on earth_ does it mean to extend an enum class? The subenum can’t have more variants, because then the inherited methods from the parent would become partial.

Hm, I suppose the subclass could have _fewer_ variants…?

---

<div class="post-metadata">

**Author:** ![est31](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/est31/32/2551_2.png) [@est31](https://internals.rust-lang.org/u/est31)\
**Post date:** [March 1, 2017, 10:53pm UTC](https://internals.rust-lang.org/t/pre-rfc-inheritance/4888/3 "2017-03-01T22:53:51Z")

</div>

See also:

> [@Summary of efficient inheritance RFCs](https://internals.rust-lang.org/t/summary-of-efficient-inheritance-rfcs/494):
>
> At next week’s weekly meeting we will discuss the proposals and implementation plan for some form of more efficient inheritance. Background We want some way to have code sharing which is more efficient than traits (in terms of time and space) and more flexible than enums. Our primary use case is the Servo DOM, but we would like this to be more general purpose too. Our constraints are: cheap field access from internal methods; cheap dynamic dispatch of methods; cheap downcasting; thin pointers…

> <https://github.com/rust-lang/rfcs/issues/349>
>
> \## Motivation
> 
> Data structures which closely fit a single inheritance model can …be very efficiently implemented in C++. Where high performance (both space and time) is crucial there is distinct disadvantage in using Rust for programs which widely use such data structures. A pressing example is the DOM in Servo. For a small example in C++, see https://gist.github.com/jdm/9900569. We require some solution which satisfies the following requirements:
> \- cheap field access from internal methods;
> \- cheap dynamic dispatch of methods;
> \- cheap downcasting;
> \- thin pointers;
> \- sharing of fields and methods between definitions;
> \- safe, i.e., doesn't require a bunch of transmutes or other unsafe code to be usable;
> \- syntactically lightweight or implicit upcasting;
> \- calling functions through smartpointers, e.g. \`fn foo(JSRef\<T\>, ...)\`;
> \- static dispatch of methods.
> \## Status
> 
> There has been discussion of potential solutions on discuss (http://discuss.rust-lang.org/t/summary-of-efficient-inheritance-rfcs/494) and in several meetings (\[minutes\](https://github.com/rust-lang/meeting-minutes/blob/master/Meeting-inheritance-2014-09-23.md) and \[minutes\](https://github.com/rust-lang/meeting-minutes/blob/master/Meeting-inheritance-2014-09-30.md)).
> 
> We clarified the requirements listed above (see the minutes for details) and established that an ergonomic solution is required. That is, we explicitly don't want to discourage programmers from using this feature by having an unfriendly syntax. We also summarised and evaluated the various proposals (again, see the minutes for details). We feel that no proposal 'as is' is totally satisfactory and that there is a bunch of work to do to get a good solution. We established a timeline (see below) for design and implementation. We would like to reserve a few keywords to reduce the backwards compatibility hazard (#342).
> \## Plan
> 
> In December the Rust and Servo teams will all be in one place and we intend to make decisions on how to provide an efficient code reuse solution and plan the implementation in detail. We'll take into account the discussions on the various RFC and discuss comment threads and of course all the community members who attend the Rust weekly meetings will be invited. We will take and publish minutes. This will lead to a new RFC. We expect implementation work to start post-1.0. If we identify backwards compatibility hazards, then we'll aim to address these before the 1.0 RC.
> \## RFC PRs
> 
> There have been numerous RFC PRs for different solutions to this problem. All of these have had useful and interesting parts and earlier RFCs have been heavily cannibalised by later ones. We believe that RFC PRs #245 and #250 are the most relevant and the eventual solution will come from these PRs and/or any ideas that emerge in the future. For a summary of some of the proposals and some discussion, see this \[discuss thread\](http://discuss.rust-lang.org/t/summary-of-efficient-inheritance-rfcs/494).
> \- https://github.com/rust-lang/rfcs/pull/254

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [March 2, 2017, 11:01am UTC](https://internals.rust-lang.org/t/pre-rfc-inheritance/4888/4 "2017-03-02T11:01:38Z")

</div>

So I have a lot of thoughts on this topic. =) I’ve not been able to find time to write down my latest, but I think the path I would like to see is roughly that we build on [RFC 1546](https://github.com/rust-lang/rfcs/pull/1546), which permits traits to have fields. Roughly speaking, traits would play the role of “abstract classes” or “interfaces” in OO terminology, and specialization would be used to handle inheritance.

Anyway, some other “related work”:

- [http://smallcultfollowing.com/babysteps/blog/2015/05/05/where-rusts-enum-shines/](http://smallcultfollowing.com/babysteps/blog/2015/05/05/where-rusts-enum-shines/)
- [http://smallcultfollowing.com/babysteps/blog/2015/05/29/classes-strike-back/](http://smallcultfollowing.com/babysteps/blog/2015/05/29/classes-strike-back/)
- [http://smallcultfollowing.com/babysteps/blog/2015/08/20/virtual-structs-part-3-bringing-enums-and-structs-together/](http://smallcultfollowing.com/babysteps/blog/2015/08/20/virtual-structs-part-3-bringing-enums-and-structs-together/)
- [http://aturon.github.io/blog/2015/09/18/reuse/](http://aturon.github.io/blog/2015/09/18/reuse/)
- [http://smallcultfollowing.com/babysteps/blog/2015/10/08/virtual-structs-part-4-extended-enums-and-thin-traits/](http://smallcultfollowing.com/babysteps/blog/2015/10/08/virtual-structs-part-4-extended-enums-and-thin-traits/)

Of those, the one on @aturon’s blog is probably most relevant to my current thoughts about traits and fields, since it describes how specialization works. But I think that the other articles are still interesting, and I’d like to see motion towards variants having their own types – **eventually**. (Or, more narrowly, towards making it more convenient to work with closed sets of classes, which is not the OO default.)

---

<div class="post-metadata">

**Author:** ![DanielFath](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/danielfath/32/5372_2.png) [@DanielFath](https://internals.rust-lang.org/u/DanielFath)\
**Post date:** [March 2, 2017, 11:23am UTC](https://internals.rust-lang.org/t/pre-rfc-inheritance/4888/5 "2017-03-02T11:23:38Z")

</div>

> [@nikomatsakis](#):
>
> closed sets of classes

Wasn't there a movement towards having enums with open set of elements? You could model both of those.

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [March 2, 2017, 11:56am UTC](https://internals.rust-lang.org/t/pre-rfc-inheritance/4888/6 "2017-03-02T11:56:22Z")

</div>

> [@DanielFath](#):
>
> Wasn't there a movement towards having enums with open set of elements? You could model both of those.

Indeed. I would call that a "trait" =)

(In my view, that's the principle difference between an enum and a trait...)

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [March 2, 2017, 11:57am UTC](https://internals.rust-lang.org/t/pre-rfc-inheritance/4888/7 "2017-03-02T11:57:05Z")

</div>

Well, ok, I simplified. It’s both open/closed and “size of the union” vs “size of the individual”. Note that that you can’t have “size of the union” with an open set of types.

---

<div class="post-metadata">

**Author:** ![tupshin](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tupshin/32/2573_2.png) [@tupshin](https://internals.rust-lang.org/u/tupshin)\
**Post date:** [March 2, 2017, 1:20pm UTC](https://internals.rust-lang.org/t/pre-rfc-inheritance/4888/8 "2017-03-02T13:20:13Z")

</div>

Huge 👍 to building on 1546. So looking forward to that.

---

<div class="post-metadata">

**Author:** ![tikue](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tikue/32/4053_2.png) [@tikue](https://internals.rust-lang.org/u/tikue)\
**Post date:** [March 2, 2017, 10:20pm UTC](https://internals.rust-lang.org/t/pre-rfc-inheritance/4888/9 "2017-03-02T22:20:28Z")

</div>

IMO the principle difference is being able to pattern match on an enum (in other words, I primarily use enums to encapsulate data and traits to encapsulate functionality (more or less)). I think closed traits would still be useful and different from enums.

---

<div class="post-metadata">

**Author:** ![eddyb](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eddyb/32/8411_2.png) [@eddyb](https://internals.rust-lang.org/u/eddyb)\
**Post date:** [March 2, 2017, 10:45pm UTC](https://internals.rust-lang.org/t/pre-rfc-inheritance/4888/10 "2017-03-02T22:45:16Z")

</div>

Interestingly enough, we do have closed traits, they’re just all private. So IMO, closing them would involve setting an “use” privacy that’s strictly larger than an “impl” privacy.

It almost sounds like our privacy system wants to be full-on ACL 😄.

---

<div class="post-metadata">

**Author:** ![dobenour](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dobenour/32/7241_2.png) [@dobenour](https://internals.rust-lang.org/u/dobenour)\
**Post date:** [March 2, 2017, 11:27pm UTC](https://internals.rust-lang.org/t/pre-rfc-inheritance/4888/11 "2017-03-02T23:27:51Z")

</div>

Java 9 does just that!

---

<div class="post-metadata">

**Author:** ![pepp](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pepp/32/1847_2.png) [@pepp](https://internals.rust-lang.org/u/pepp)\
**Post date:** [March 3, 2017, 11:08am UTC](https://internals.rust-lang.org/t/pre-rfc-inheritance/4888/12 "2017-03-03T11:08:07Z")

</div>

Loud NO to virtual methods. This was discussed years ago and the outcome was that creating parallel dynamic dispatch mechanism to trait objects is wrong direction.

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [March 3, 2017, 1:17pm UTC](https://internals.rust-lang.org/t/pre-rfc-inheritance/4888/13 "2017-03-03T13:17:55Z")

</div>

> [@eddyb](#):
>
> Interestingly enough, we do have closed traits, they're just all private. So IMO, closing them would involve setting an "use" privacy that's strictly larger than an "impl" privacy.

I've had thoughts along these lines too. I also want to have `default(restricted)` for specialization, which is obviously very related.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:28am UTC](https://internals.rust-lang.org/t/pre-rfc-inheritance/4888/14 "2019-03-25T08:28:05Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
