# Consistent `class` and `interface` syntax

<!--
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
Exceptions. See /LICENSE for license information.
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-->

[Pull request](https://github.com/carbon-language/carbon-lang/pull/2760)

<!-- toc -->

## 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)

<!-- tocstop -->

## 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:

    <!-- prettier-ignore -->
    > `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:

<!-- prettier-ignore -->
> `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_ `;` <br> `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.
