# Consistent `class` and `interface` syntax [Pull request](https://github.com/carbon-language/carbon-lang/pull/2760) ## Table of contents - [Abstract](#abstract) - [Problem](#problem) - [Background](#background) - [Proposal](#proposal) - [Details](#details) - [Class inheritance](#class-inheritance) - [Class implementing an interface](#class-implementing-an-interface) - [Class conditional implementation](#class-conditional-implementation) - [Adapters](#adapters) - [Interfaces](#interfaces) - [Future work: mixins](#future-work-mixins) - [Rationale](#rationale) - [Alternatives considered](#alternatives-considered) - [Use `extends` instead of `extend`](#use-extends-instead-of-extend) - [Allow interfaces to `require` another interface without writing `Self impls`](#allow-interfaces-to-require-another-interface-without-writing-self-impls) - [Allow other kinds of `where` clauses after `require`](#allow-other-kinds-of-where-clauses-after-require) - [Continue to use `impl as` for interface requirements](#continue-to-use-impl-as-for-interface-requirements) - [Continue to use `adapter` or `adaptor` instead of `adapt`](#continue-to-use-adapter-or-adaptor-instead-of-adapt) - [Use some other syntax for extending adapters](#use-some-other-syntax-for-extending-adapters) - [Continue to have some term for "external" or non-extended implementations](#continue-to-have-some-term-for-external-or-non-extended-implementations) - [More direct support for conditionally implementing internal interfaces](#more-direct-support-for-conditionally-implementing-internal-interfaces) - [Use `external` consistently instead of `extend`](#use-external-consistently-instead-of-extend) - [Use `mix` keyword for mixins](#use-mix-keyword-for-mixins) - [Allow more control over access to mixins](#allow-more-control-over-access-to-mixins) - [List base class in class declaration](#list-base-class-in-class-declaration) ## Abstract Update syntax of `class` and `interface` definitions to be more consistent. Constructs that add names to the class or interface from another definition are always prefixed by the `extend` keyword. Implements the decisions in: - [#995: Generics external impl versus extends](https://github.com/carbon-language/carbon-lang/issues/995), - [#1159: adaptor versus adapter may be harder to spell than we'd like](https://github.com/carbon-language/carbon-lang/issues/1159), - [#2580: How should Carbon handle conditionally implemented internal interfaces](https://github.com/carbon-language/carbon-lang/issues/2580), and - [#2770: Terminology for internal and external implementations](https://github.com/carbon-language/carbon-lang/issues/2770). ## Problem Classes and adapters, prior to this proposal, use `impl` to say that an interface is [implemented internally](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/terminology.md#internal-impl), which means that the names that are members of the interface are included as names of the class. The keyword `external` is added to indicate the names should not be included. Interfaces and named constraints, in contrast, use `impl` to mean another interface is required, but its names are not included. Instead, to include the names, the `extends` keyword used instead of `impl`. | Include names: | Yes | No | | ------------------------- | --------- | --------------- | | `class`, `adapter` | `impl` | `external impl` | | `interface`, `constraint` | `extends` | `impl` | In the time since this syntax has been introduced, we have found `external` in particular easy to accidentally omit. In addition to resolving this inconsistency, it would be an advantage if readers of a class could quickly scan the definition to identify other places to look for members that contribute to the class' API. ## Background These proposals that defined the syntax for these entities that are being modified: - [#553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553) defined the syntax for classes implementing interfaces, internally or externally, and the syntax for named constraints (then "structural interfaces") and interfaces requiring or extending other interfaces. - [#731: Generics details 2: adapters, associated types, parameterized interfaces](https://github.com/carbon-language/carbon-lang/pull/731) defined the syntax for adapters and extending adapters. - [#1084: Generics details 9: forward declarations](https://github.com/carbon-language/carbon-lang/pull/1084) allowed forward declaration of implementations, so internal `impl` declarations may appear outside of a class definition, and `external impl` declarations may appear inside. - [#777: Inheritance](https://github.com/carbon-language/carbon-lang/pull/777) defined the syntax for a class to extend a base class. No proposal so far has defined how forward declarations work for classes. The rule used for forward `interface`, `constraint`, and `impl` declarations is that the declaration part of the definition is everything up to the opening `{` of the definition body. See [the forward declaration section of the Generics details design doc](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#forward-declarations-and-cyclic-references) added in proposal [#1084: Generics details 9: forward declarations](https://github.com/carbon-language/carbon-lang/pull/1084). This proposal incorporates the decisions made in these question-for-leads issues: - [#995: Generics external impl versus extends](https://github.com/carbon-language/carbon-lang/issues/995), - [#1159: adaptor versus adapter may be harder to spell than we'd like](https://github.com/carbon-language/carbon-lang/issues/1159), - [#2580: How should Carbon handle conditionally implemented internal interfaces](https://github.com/carbon-language/carbon-lang/issues/2580), and - [#2770: Terminology for internal and external implementations](https://github.com/carbon-language/carbon-lang/issues/2770). Some of thinking around the resolution of #995 was documented in [issue #2293: reconsider syntax for internal / external implementation of interfaces](https://github.com/carbon-language/carbon-lang/issues/2293), which was closed as a duplicate of #995. In addition to modifying syntax from previous proposals, [#995](https://github.com/carbon-language/carbon-lang/issues/995) also gives a syntax for using a mixin in a class. Mixins are described as a use case in [#561: Basic classes: use cases, struct literals, struct types, and future work](https://github.com/carbon-language/carbon-lang/pull/561), but have not been added in any proposal. Question-for-leads issue [#1000: Mixins: base classes or data members?](https://github.com/carbon-language/carbon-lang/issues/1000), does state that a class will treat a mixin syntactically like a data member instead of a base class. ## Proposal Any declaration that adds the names from another entity shall start with the (new) `extend` keyword. This includes: - _Inheritance_: A class now indicates that it inherits from a base class using an > `extend base:` _base-class_ `;` declaration inside the class definition. The `extend` keyword indicates that the API of the base class is included. - _Adapters_: Adapter types are now declared as a class, with an > [ `extend` ] `adapt` _adapted-class_ `;` declaration inside the definition, as an alternative to a base class declaration. The optional `extend` keyword controls whether the API of the adapted class is included. - _Implementations_: Internal implementations are marked with the `extend` keyword on the declaration inside the class. Only the declaration inside the class, which is required for internal implementations, uses the `extend` keyword. External implementations are not marked. > [ `extend` ] `impl` ... - _Interfaces_: The `extends` declaration in an interface definition is replaced by an `extend` declaration, with no change except removing the `s` from the end of the keyword. Other interface requirements are now written using a `require` declaration, with a constraint that matches a `where` clause. This means > `impl as` _required-interface_ `;` will now be written as > `require Self impls` _required-interface_ `;` and > `impl` _type-expression_ `as` _required-interface_ `;` will now be written as > `require` _type-expression_ `impls` _required-interface_ `;` For now, only the `impls` forms of `where` clauses are permitted after `require`. In summary: | Before | After | | ------------------------------- | --------------------------------------- | | `class D extends B { ... }` | `class D { extend base: B; ... }` | | `external impl C as Sub;` | `impl C as Sub;` | | `class C { impl as Sortable; }` | `class C { extend impl as Sortable; }` | | `adapter A for C { ... }` | `class A { adapt C; ... }` | | `adapter A extends C { ... }` | `class A { extend adapt C; ... }` | | `interface I { impl as J; }` | `interface I { require Self impls J; }` | | `interface I { impl T as J; }` | `interface I { require T impls J; }` | | `interface I { extends J; }` | `interface I { extend J; }` | None of `adapter`, `extends`, `external` will continue to be keywords. To match these changes, "internal implementations" will now be referred to as "extended implementations," and we will no longer use "external" to refer to implementations. In addition, we drop the syntax for conditionally implemented internal interfaces. Instead, an external interface implementation can be combined with aliases to the members of the interface. ## Details ### Class inheritance What was previously written: ``` base class B; class D extends B; class D extends B { ... } ``` is now written: ``` base class B; class D; class D { extend base: B; ... } ``` An extend base class declaration may appear in the body of a class definition, and has this form: > `extend` `base` `:` _type-expression_ `;` The `extend base: B;` declaration must appear before any other data member declaration, including any [mixin declaration](#future-work-mixins), once those are added. This reflects both the importance of the information, and the fact that the base subobject appears first in the memory layout of objects. Note that `base` is already a keyword, for example used in `base class` declarations. The colon in `base: B` is to indicate that `base` acts like a data member for [purposes of initialization](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/classes.md#constructors). This makes the part of a class definition that is used in forward declarations be exactly the part before the curly braces (`{`...`}`). Before this proposal, class forward declarations would exclude the `extends` clause from the first line of the class definition. This change makes classes consistent with other entities that may be forward declared. ### Class implementing an interface What was previously written: ``` interface Sortable; interface Add; interface Sub; class C; // Forward declaration says whether external. impl C as Sortable; external impl C as Add; class C { // Internal impl contributes to the API. impl as Sortable; // External impl of an operator. external impl as Add; } // External impl of an operator. external impl C as Sub; // Definition of `impl` declared earlier. impl C as Sortable { ... } external impl C as Add { ... } ``` is now written: ``` interface Sortable; interface Add; interface Sub; class C; // Forward declaration same whether extended or not. impl C as Sortable; impl C as Add; class C { // Extended impl contributes to the API. extend impl as Sortable; // (Non-extended) Impl of an operator. impl as Add; } // (Non-extended) Impl of an operator. impl C as Sub; // Definition of `impl` declared earlier. impl C as Sortable { ... } impl C as Add { ... } ``` Whether an interface is extended or not is now only reflected in its declaration inside the class body, not in any declaration or definition outside. An `impl` declaration, with this proposal, must have one of these two forms: - Without an `extend` keyword prefix, used for non-extended `impl` declarations and for all `impl` declarations outside of a class body: > `impl` [`forall` `[` _deduced-parameters_ `]`] [_type-expression_] `as` > _facet-type-expression_ (`;`|`{` _impl-body_ `}`) The _type-expression_ is required outside of a class body, otherwise it defaults to `Self`. - With an `extend` keyword prefix, to indicate this implementation is extended, only in a class body: > `extend` `impl` `as` _facet-type-expression_ (`;`|`{` _impl-body_ `}`) Note that this form does not allow either a `forall` clause nor a _type-expression_ before the `as` keyword. This reflects the restriction that [wildcard `impl` declarations must never be extended (formerly: "always be external")](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#wildcard-impl-declarations), and that this proposal removes support for [extended (formerly "internal") conditional implementation](#class-conditional-implementation). ### Class conditional implementation We remove direct support for conditionally implemented extended (formerly "internal") interfaces, called [conditional conformance](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#conditional-conformance). We can work around this restriction by using an non-extended interface implementation and aliases to the members of the interface. What was previously written: ``` interface Printable { fn Print[self: Self](); } class Vector(T:! type) { // ... impl forall [U:! Printable] Vector(U) as Printable { fn Print[self: Self](); } } ``` is now written: ``` interface Printable { fn Print[self: Self](); } class Vector(T:! type) { // ... alias Print = Printable.Print; } impl forall [U:! Printable] Vector(U) as Printable { fn Print[self: Self](); } ``` The way this works is that `Vector.Print` is equivalent to `Vector.(Printable.Print)`, which may or may not be defined. The name `Vector.Print` can no longer be conditional, and the meaning of that name is fixed. However, the implementation of `Printable` for `Vector(T)` may not exist for some types `T`. ### Adapters What was previously written: ``` class C; // Forward declarations of adapters. adapter A for C; adapter E extends C; // Definitions of an adapter. adapter A for C { ... } // Definition of an extending adapter. adapter E extends C { ... } ``` is now written: ``` class C; // Forward declarations of adapters. class A; class E; // Definitions of an adapter. class A { adapt C; ... } // Definition of an extending adapter. class E { extend adapt C; ... } ``` Note: - Adapters are now a special case of classes, not a distinct top-level declaration. - Classes with `adapt` still must not contain anything that was previously forbidden for adapters: no fields, no base class, no virtual methods, no implementations of virtual methods, and so on. - The `adapt` declaration must appear before [mixin declarations](#future-work-mixins), if any. - The syntax for an `adapt` declaration inside a class body is: > [`extend`] `adapt` _type-expression_ `;` ### Interfaces What was previously written: ``` interface A { let T:! Type; } interface B { let U:! Type; } interface C(V:! Type) { } interface I { // `A`'s interface is incorporated into `I`: extends A where .T = i32; // No impact on `I`s interface, but an // implementation must exist: impl as B where .U = i32; // Implementation must exist on another type: impl i32 as C(Self); } ``` is now written: ``` interface A { let T:! Type; } interface B { let U:! Type; } interface C(V:! Type) { } interface I { // `A`'s interface is incorporated into `I`: extend A where .T = i32; // No impact on `I`s interface, but an // implementation must exist: require Self impls B where .U = i32; // Implementation must exist on another type: require i32 impls C(Self); } ``` Notes: - The same change applies to named constraints, and is intended to be used in the future for named predicates used as template constraints. - One syntax for constraints in either `where` clauses or `require` declarations. - Want to open up the syntax to expressing more general constraints. - Syntax for a `require` declaration in an interface or named constraint: > `require` _type-expression_ `impls` _facet-type-expression_ `;` As [with `impl`...`as` declarations before](/docs/design/generics/details.md#interface-requiring-other-interfaces-revisited), a `require` declaration must use `Self`, either to the left or right of `impls`. Note that `require` only supports this subset of `where` clause expressions. Adding other kinds of constraints is future work. - Syntax for an `extend` declaration in an interface or named constraint: > `extend` _facet-type-expression_ `;` ## Future work: mixins Mixins have not been defined in a proposal so far. However, part of the process of resolving [issue #995](https://github.com/carbon-language/carbon-lang/issues/995) was deciding on a syntax for including a mixin in a class. This was done in order to make sure that class declarations that included names from another entity were treated consistently, for example always starting with the `extend` keyword. ``` // Mixin declarations and definitions are // outside the scope of this proposal. mixin M1; mixin M2; class C { // Mixing in mixin M1 extend m: M1; // Mixing in mixin M2. This member is not named. // Initialized using `M2.MakeDefault()`. extend _: M2 = M2.MakeDefault(); // Alternative to the above `M2` that uses a // private name instead of no name: extend private m2: M2; } ``` The declaration that a class uses a mixin is called a "mix" declaration. The syntax of a mix declaration is: > `extend` [`private`|`protected`] (`_`|_id_) `:` _mixin-expression_ [`=` > _initializer-expression_] `;` The _id_ part of the mix declaration defines the name assigned to that mixin subobject. This name is may be used to access members of the mixin and to initialize the mixin in a constructor for the class. The optional `private` or `protected` access specifier controls the access to this name. With this proposal, base class declarations appear in the body of the class definition, like data members, so decision of whether mixins are more like base classes or data members of issue [#1000: Mixins: base classes or data members?](https://github.com/carbon-language/carbon-lang/issues/1000) is less significant. Like base classes, the mix declaration syntax begins with `extend`. Like data members, a class may have multiple mix declarations and they may be intermixed with field declarations. The layout of the memory of an object reflects the order of the declarations in the class body, defining the order of the mixin and field subobjects. ## Rationale The main reason for the new syntax is consistency and simplification: - The use of the `extend` keyword is the consistent way to mark what other entities are consulted during name lookup. - The `class` declaration is simplified by moving more into the definition body. - Making adapters a kind of class removes a kind of top-level declaration, a simplification, and matches how base classes are declared, a consistency. - Dropping the class conditional implementation is a simplification. These consistency and simplification improvements help: - ease the implementation of [language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem) by reducing the size of the language, and providing regularities implementations can use to reuse code or more easily identify relevant parts of the code for queries; - make Carbon code [easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write). - teaching the language, since there is less to learn. ## Alternatives considered ### Use `extends` instead of `extend` Keyword `extend` was chosen over `extends` to parallel `impl`, a declaration, instead of `impls`, a binary predicate, decided in [issue #2495](https://github.com/carbon-language/carbon-lang/issues/2495) and accepted in [proposal #2483](https://github.com/carbon-language/carbon-lang/pull/2483). We chose to use `require` instead of `requires` and `adapt` instead of `adapts` for the same consistency. ### Allow interfaces to `require` another interface without writing `Self impls` We [considered](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1418387971) allowing `interface I { require J; }` as a short-hand for `interface I { require Self impls J; }`. This is something we would consider adding in the future based on experience with the current approach, but for now we wanted to maintain consistency with the constraint syntax of `where` clauses. This decision and rationale was described in [this comment in #995](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1416659207). ### Allow other kinds of `where` clauses after `require` The decision on [#995](https://github.com/carbon-language/carbon-lang/issues/995), see [1](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1439336141) and [2](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1496781087), called for the same constraint syntax after `require` as we are using after `where`. This proposal _only_ allows `impls` clauses after `require`, since there were concerns about the other kinds of clauses: - We had questions about what syntax to use to refer to members of the interface, such as associated types, to constrain them. Must they start with `Self.` or `.`? See [this comment thread on #2760](https://github.com/carbon-language/carbon-lang/pull/2760#discussion_r1213789364). - Modifying the constraints on an associated type after the declaration for that associated type was not something we clearly wanted to allow. Allowing that would mean having to read the whole interface definition body to understand a single member. - It was unclear if rewrite constraints (using `=` instead of `==`), would be allowed in a `require` declaration, and if they were, whether they would be changed into equality constraints (as if they were declared using `==`). See [this comment on #2760](https://github.com/carbon-language/carbon-lang/pull/2760#discussion_r1213791304). - It would have provided more different ways of declaring equivalent interfaces. This concern was raised [in this comment on #2760](https://github.com/carbon-language/carbon-lang/pull/2760#discussion_r1214571215). For now, we only needed to replace the existing uses of `impl as` constraints, which had none of these concerns. We did not want to block this proposal, so we made sure the `require` clauses were consistent with that _subset_ of `where` clauses. ### Continue to use `impl as` for interface requirements There were a few reasons motivating the change to use the new `require` declarations in interfaces and named constraints, instead of using `impl as` to match how a type could satisfy that requirement. These mostly came down to some observed breaks in the parallel structure between the requirement in interfaces and the satisfaction of that requirement in types. - Whether an interface `I` extends or just requires another interface `J` is independent of whether a type implementing `I` extends or just implements `J`. - If `R` requires interface `I`, the implementation of `R` for a type won't have the implementation of `I` as a nested sub-block. - With the change in [#2173: Associated constant assignment versus equality](https://github.com/carbon-language/carbon-lang/pull/2173), the behavior of `impl as` in interfaces is different from in classes with respect to rewrites of associated types, motivating a change to make those look more different. Furthermore, we had a desire to be able to express the full range of constraints in `where` clauses in named constraints, and we wanted the transformation from a `where` clause to a named constraint to be straightforward. We also wanted the syntax for constraints to be the same between interfaces and named constraints, at least for all constraints that were allowed in both. This was discussed in [#generics-and-templates on 2023-01-30](https://discord.com/channels/655572317891461132/941071822756143115/1069691751968817283) and in [issue #995](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1412478644). ### Continue to use `adapter` or `adaptor` instead of `adapt` We didn't want to allow both `adapter` and `adaptor`, since that adds complexity for readers and tooling, but neither seemed clearly dominant enough in usage to pick one over the other. By moving the declaration into the body of the class definition, we were able to switch from the noun form to the verb form of `adapt`, which doesn't have an alternate form in common usage. See [#1159: adaptor versus adapter may be harder to spell than we'd like](https://github.com/carbon-language/carbon-lang/issues/1159) for the discussion. We also considered using `adapts` in a class declaration, as in `class PlayableSong adapts Song { ... }`, see [this comment in #1159](https://github.com/carbon-language/carbon-lang/issues/1159#issuecomment-1316669416). This would have also worked, but was not consistent with our resolution of [#995: Generics external impl versus extends](https://github.com/carbon-language/carbon-lang/issues/995). ### Use some other syntax for extending adapters In the [open discussion on 2023-02-27](https://docs.google.com/document/d/1gnJBTfY81fZYvI_QXjwKk1uQHYBNHGqRLI2BS_cYYNQ/edit?resourcekey=0-ql1Q1WvTcDvhycf8LbA9DQ#heading=h.9steyq834zuq), we discussed some alternatives to `extend adapt` _adapted-class_ `;`: - Adding `and` to make it read more like fluent English: > `extend and adapt` _adapted-class_ `;` However, this felt arbitrary and not compositional. - Make the extending and adapting be separate declarations: > `extend` _adapted-class_ `;`
`adapt` _adapted-class_ `;` This felt too repetitive. - Make the only way to make an extending adapter be trying to inherit from a final base class > `extend base:` _adapted-class_ `;` However, this meant using the same syntax for two different things that could only be distinguished by looking at the declaration of the adapted class, which could be far away. It also would have meant making an extending adapter of a non-final class much more cumbersome. Ultimately, we decided that `extend adapt` would be the most compositional way of combining `extend` and `adapt`, so that is what users would expect. Reading like natural English was not considered essential. ### Continue to have some term for "external" or non-extended implementations The fact that there were some different rules for external implementations was brought up in [this post in #2770](https://github.com/carbon-language/carbon-lang/issues/2770#issuecomment-1509288478). However, [this reply](https://github.com/carbon-language/carbon-lang/issues/2770#issuecomment-1515522070) pointed out those rules could be clearly stated in terms of where you are allowed to write `extend`. That same post made the convincing argument that to get the maximum benefit of the decision on [#995](https://github.com/carbon-language/carbon-lang/issues/995), we should treat `extend` and `impl` as separate orthogonal concepts as much as possible. ### More direct support for conditionally implementing internal interfaces We considered two different ways of more directly supporting conditionally extending a class by an interface: - Prior to this proposal, both name lookup and the implementation were conditional on the same condition. This has the disadvantage of entangling the concerns of name lookup and implementation, and was considered a complex and difficult model. - We also considered fully separating these features, and allowing a type to separately extend its API with an interface and then only conditionally implement that interface. This would allow name lookup to succeed unconditionally, but in cases where the names were in fact not implemented it would produce an error. Both of these approaches would have required some support for expressing this in the new syntax. None of the syntactic approaches we considered were found to be satisfactory. By making name lookup never conditional, it made it much easier to have a consistent marker for declarations that extended name lookup. Ultimately, the alternative of not having a dedicated syntax to support this case seemed the simplest in the short term, given the workaround of conditional external (non-extending) implementation paired with aliases that provide the name lookup, unconditionally. We can always add dedicated syntax later, given sufficient motivating information. The options were considered in [#2580: How should Carbon handle conditionally implemented internal interfaces](https://github.com/carbon-language/carbon-lang/issues/2580). ### Use `external` consistently instead of `extend` We considered making "extending name lookup" the default and overriding that default with the `external` keyword. The argument for this option rested on it being more convenient to express conditional internal implementation, and wasn't seen as attractive once that feature was removed. In the discussion, we generally preferred marking additional places to consult in name lookup since that was something we expected readers of the code to want to specifically look for. This option was proposed as the third option in the [original #995 question](https://github.com/carbon-language/carbon-lang/issues/995#issue-1085174338), and was considered in [this comment](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1006096692). ### Use `mix` keyword for mixins We considered a variety of different syntax options for using a mixin for a type in [this comment on #995](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1315948818). Many of them used the `mix` keyword, but we ultimately decided that `mix` was redundant with saying `extend`, which we wanted to be included with all constructs extending the type's API by another entity. ### Allow more control over access to mixins There were three different aspects of mixins that we considered giving control over access: - the inclusion of names exported by the mixin into the mixer class, - the ability to cast between the mixin and the mixer class types, and - the ability to use the name of the mixin given by the mixer class to access members of the mixin. This was particularly relevant when we were considering separate declarations for declaring the mixin member and the API extension ([1](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1315948818), [2](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1317598076)). This approach had the problem that the common case for mixins was extending the API, which would not have been the default. The only examples we had where the mixer class would not want to include the names exported by the mixin were cases where the mixin had nothing to export. This led to [the position](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1325746398) that the mixin would control which of its member would be included into the mixer class' API -- that is the mixin would "inject" members rather than "export" them and leave it up to the mixer class to import them. We had concerns that there might be name conflicts, but we thought those might be handled by some other mechanism. This is being considered in question-for-leads issue [#2745: Name conflicts beyond inheritance](https://github.com/carbon-language/carbon-lang/issues/2745). We wanted mixin member names to behave consistently like other class member names, and so default to public but can have a `private` modifier to make private, following [#665: `private` vs `public` _syntax_ strategy, as well as other visibility tools like `external`/`api`/etc.](https://github.com/carbon-language/carbon-lang/issues/665). We decided to put the `private` keyword _between_ the `extend` keyword and the member name for two reasons: - to make it easier to scan for all uses of `extend` in a class, and - to make it clearer that the `private` access control only applies to the member name, not what the `extend` controls. We did not see a use case for controlling the ability to cast between the mixin and the mixer class types separately from being able to access the name the mixin member of the mixin class. This was consistent with our desire to limit declarations to a single access control specifier per declaration, see [this update in #995](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1322892195). ### List base class in class declaration By moving the base class into the class body, we accomplished three things: - made forward declarations shorter, - made it possible to inherit from a type declared inside the body of the class definition, and - allowed greater consistency, all API extensions are now declarations in the body of the class definition starting with `extend`. This was decided in [this comment on #995](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1317598076). This left open the question of what keyword introducer to use in base class declarations, since using `base` would cause an ambiguity with declaring a member class that could be extended, as considered in [this comment](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1320614313). Ultimately we avoided this problem by requiring base class declarations to always begin with `extend`, not support any form of private or protected inheritance (see [this comment](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1325746398)), and not support any combination of an `extend` declaration with a member class declaration.