mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 10:21:04 +01:00
This PR corrects misspellings identified by the [check-spelling action](https://github.com/marketplace/actions/check-spelling). The misspellings have been reported at https://github.com/jsoref/carbon-lang/commit/38a1c1640151899fd6da0442a92557f9543b6280#commitcomment-79197316 The action reports that the changes in this PR would make it happy: https://github.com/jsoref/carbon-lang/commit/173c8f9083a68aa61f7cfe94f720f1e5dc7f1ea3 Note: this PR does not include the action. If you're interested in running a spell check on every PR and push, that can be offered separately. Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
207 lines
6.0 KiB
Markdown
207 lines
6.0 KiB
Markdown
# 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).
|