# What can be done with an incomplete interface [Pull request](https://github.com/carbon-language/carbon-lang/pull/2347) ## Table of contents - [Abstract](#abstract) - [Problem](#problem) - [Background](#background) - [Proposal](#proposal) - [Rationale](#rationale) - [Alternatives considered](#alternatives-considered) - [Allow declaration and definition in different files](#allow-declaration-and-definition-in-different-files) - [No specific restriction on `where` clauses on incomplete constraints](#no-specific-restriction-on-where-clauses-on-incomplete-constraints) - [Don't allow combinations of incomplete constraints as in `C & D`](#dont-allow-combinations-of-incomplete-constraints-as-in-c--d) ## Abstract Clarify what can and cannot be done with a incomplete interface or named constraint. ## Problem For purposes of this proposal, the term _constraints_ refers to interfaces and named constraints. Interfaces do not require any different treatment from named constraints, and treating them the same is good for simplicity and uniformity. We want to support forward declaring constraints so that they may be used before they are allowed to be defined, due to recursion or a reference cycle. Some uses require the definition of the constraint to be visible to be checked, however. In some cases, those checks may be delayed at the cost of complexity in the implementation of the compiler. This proposal aims to specify what uses are allowed, particularly those cases that were not covered by [the previous proposal on forward declarations](https://github.com/carbon-language/carbon-lang/pull/1084). ## Background Proposal [#1084: Generics details 9: forward declarations](https://github.com/carbon-language/carbon-lang/pull/1084) originally laid out the rules for incomplete constraints. Since then, the [discussion on 2022-10-12](https://docs.google.com/document/d/1tEt4iM6vfcY0O0DG0uOEMIbaXcZXlNREc2ChNiEtn_w/edit#heading=h.q7afaawbc5k) considered how we needed to update and fill in those rules, as part of an effort to implement those rules in the Carbon Explorer. ## Proposal The new rule details have been added by this proposal PR to the [Forward declarations and cyclic references: declaring interfaces and named constraints](/docs/design/generics/details.md#declaring-interfaces-and-named-constraints) section of [Generics: details design document](/docs/design/generics/details.md). ## Rationale This proposal is balancing the expressivity needed to make code easier to write with implementation simplicity, both concerns of Carbon's ["code that is easy to read, understand, and write"](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write) goal. ## Alternatives considered ### Allow declaration and definition in different files In particular, we considered allowing the declaration of an interface or named constraint in an API file and the definition in the impl file of the same library. We considered some use cases that might benefit from this in [#931](p0931.md#private-interfaces-in-public-api-files) and [#971](https://github.com/carbon-language/carbon-lang/issues/971). In [#generics-and-templates on 2022-10-24](https://discord.com/channels/655572317891461132/941071822756143115/1034207895392358431), we decided those use cases would be okay including the definition of the private interface in the API file. So to support checking for invalid uses of an incomplete interfaces with information local to that file, we reaffirmed the decision in #971 and implemented in proposal [#1084](https://github.com/carbon-language/carbon-lang/pull/1084) to require the definition to be in the same file as the declaration. ### No specific restriction on `where` clauses on incomplete constraints We considered not having a specific rule preventing any `where` clause on an incomplete constraint. The idea is that the problematic cases, such as those that access members of the constraint like `where .X = T`, are already forbidden. By removing this rule, we would allow constructions like `C where Vector(.Self) is Hashable` for incomplete `C`. We decided to wait until we had a motivating use case to allow this, and start with the more restrictive rule. ### Don't allow combinations of incomplete constraints as in `C & D` We considered forbidding the combination of incomplete constraints with the `&` operator, because otherwise we would not be able to diagnose conflicts between the two constraints. For example, ```carbon constraint C; constraint D; // Can't tell if there is a conflict between `C` and `D`. fn F[T:! C & D](x: T); // These definitions of `C` and `D` conflict. constraint C { extends I where .X = i32; } constraint D { extends I where .X = bool; } ``` Since our existing examples of using forward declarations to define a graph with cyclic references between the edge and node interfaces needed this feature, we decided to support it. This motivated the requirement that [the definition be in the same file as the declaration](#allow-declaration-and-definition-in-different-files), so the error could be detected once the compiler reached the definitions.