# Generics details part 1

<!--
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/553)

<!-- toc -->

## Table of contents

-   [Problem](#problem)
-   [Background](#background)
-   [Proposal](#proposal)
-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)
-   [Alternatives considered](#alternatives-considered)
    -   [Interface implementation syntax](#interface-implementation-syntax)
        -   [`for` instead of `as` in external `impl`](#for-instead-of-as-in-external-impl)
        -   [No `as` for inline `impl`](#no-as-for-inline-impl)
        -   [No `external` for external `impl`](#no-external-for-external-impl)
        -   [Out-of-line impl](#out-of-line-impl)
        -   [`extend` blocks](#extend-blocks)
    -   [Others](#others)

<!-- tocstop -->

## Problem

We want to Carbon to have a high quality generics feature that achieves the
goals set out in [#24](https://github.com/carbon-language/carbon-lang/pull/24).
This is too big to land in a single proposal. This proposal goes into the
details of the core of the feature, and provides an outline covering future
work. It covers:

-   interfaces
-   implementing interfaces for types
-   resolving name conflicts
-   facet types
-   type-types as the way of describing type variables
-   structural interfaces
-   combining interfaces
-   interface requirements and extension
-   type compatibility

## Background

This is a follow on to these previous generics proposals:

-   [Generics goals #24](https://github.com/carbon-language/carbon-lang/pull/24)
-   [Generics terminology #447](https://github.com/carbon-language/carbon-lang/pull/447)
-   [Generics overview #524](https://github.com/carbon-language/carbon-lang/pull/524)

The content for this proposal was extracted from a larger
[Generics combined draft proposal](https://github.com/carbon-language/carbon-lang/pull/36).

## Proposal

This is a proposal to add
[this detailed design document](/docs/design/generics/details.md).

## Rationale based on Carbon's goals

Much of this rationale was captured in the
[Generics goals proposal](https://github.com/carbon-language/carbon-lang/pull/24).

## Alternatives considered

### Interface implementation syntax

The interface implementation syntax was decided in
[question-for-leads issue #575](https://github.com/carbon-language/carbon-lang/issues/575).

```
struct Song {
  // data and methods ...
  impl as Printable {
    method (me: Self) Print() { ... }
  }
}
external impl Song as Comparable { ... }
```

This proposal includes additional discussion and additional alternatives.

#### `for` instead of `as` in external `impl`

In this option, the interface name comes before the type name.

```
struct Song { ... }
external impl Comparable for Song { ... }
```

Advantage:

-   This ordering used by Rust.

Disadvantages:

-   We prefer the type name before the interface name (using `as`), since having
    the type first and outer is consistent with those implemented in `struct`
    declarations. It also seems more natural to express the parameters to the
    interface in terms of the parameters and associated items of the type than
    the other way around.
-   The `Song as Comparable` phrase is the name of the facet type that is being
    implemented.

#### No `as` for inline `impl`

```
struct Song {
  // data and methods ...
  impl Printable {
    method (me: Self) Print() { ... }
  }
}
```

Advantage:

-   More concise, so less to read and write.

Disadvantage:

-   Less consistent with the `external impl` syntax.
-   Less consistent with the planned inline conditional impl syntax.

#### No `external` for external `impl`

```
struct Song { ... }
impl Song as Comparable { ... }
```

Advantage:

-   More concise, so less to read and write.

Disadvantages:

-   Less explicit that the methods of this impl definition are not contributing
    to unqualified API of the type.
-   This kind of implementation is naturally referred to as "external",
    especially when contrasting with "inline impl".

#### Out-of-line impl

We considered an out-of-line syntax for declaring and defining interface `impl`
blocks, to be consistent with the `external impl` declarations. For example:

```
struct Song { ... }
impl Printable for Song { ... }
external impl Comparable for Song { ... }
```

The main advantage of this syntax was that it was uniform across many cases,
including
[conditional conformance](/docs/design/generics/details.md#conditional-conformance).
It wasn't ideal across a number of dimensions though.

-   It repeated the type name which was redundant and verbose
-   It could affect the API of the type outside of the type definition.

#### `extend` blocks

Instead of the `external impl` statement, we considered putting all external
implementations in an `expand` block.

```
struct Song {
  impl Printable { ... }
}
expand Song {
  impl Comparable { ... }
}
```

Advantages:

-   This option is most similar to the
    [approach used by Swift](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID277).
-   Easier to copy-paste an `impl` between a `struct` definition and an `expand`
    block.

The `expand` approach had some disadvantages:

-   Implementations were indented more than the `external impl` approach.
-   Extra ceremony in the case of only implementing one type for an interface.
    This case is expected to be common since external implementations will most
    often be defined with the interface.
-   When implementing multiple interfaces in a single `expand` block, the name
    of the type being expanded could be far from the `impl` declaration and hard
    to find.

We originally used `extend` instead of `expand` but that collided with using
`extends` for interface extension and derived classes.

### Others

Other alternatives considered will be in a future proposal. Some of them can be
seen in a rough form in
[#36](https://github.com/carbon-language/carbon-lang/pull/36).
