# Generics details part 1 [Pull request](https://github.com/carbon-language/carbon-lang/pull/553) ## 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) ## 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).