Kaynağa Gözat

Update generics goals doc (#3060)

This reflects changes from #2138 , plus a number of other updates,
including reflecting that we have decided to include templates in
Carbon.
josh11b 2 yıl önce
ebeveyn
işleme
916bb4022a
2 değiştirilmiş dosya ile 161 ekleme ve 163 silme
  1. 160 162
      docs/design/generics/goals.md
  2. 1 1
      proposals/p2274.md

+ 160 - 162
docs/design/generics/goals.md

@@ -14,13 +14,13 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 -   [Background](#background)
     -   [Generic parameters](#generic-parameters)
     -   [Interfaces](#interfaces)
-    -   [Relationship to templates](#relationship-to-templates)
--   [Goals](#goals)
+-   [Templates](#templates)
+-   [Checked-generic goals](#checked-generic-goals)
     -   [Use cases](#use-cases)
         -   [Generic programming](#generic-programming)
         -   [Upgrade path from C++ abstract interfaces](#upgrade-path-from-c-abstract-interfaces)
         -   [Dependency injection](#dependency-injection)
-        -   [Generics instead of open overloading and ADL](#generics-instead-of-open-overloading-and-adl)
+        -   [Checked generics instead of open overloading and ADL](#checked-generics-instead-of-open-overloading-and-adl)
     -   [Performance](#performance)
     -   [Better compiler experience](#better-compiler-experience)
     -   [Encapsulation](#encapsulation)
@@ -34,11 +34,10 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
     -   [Interfaces are nominal](#interfaces-are-nominal)
     -   [Interop and evolution](#interop-and-evolution)
     -   [Bridge for C++ customization points](#bridge-for-c-customization-points)
--   [What we are not doing](#what-we-are-not-doing)
+-   [What we are not doing with checked generics](#what-we-are-not-doing-with-checked-generics)
     -   [Not the full flexibility of templates](#not-the-full-flexibility-of-templates)
-    -   [Template use cases that are out of scope](#template-use-cases-that-are-out-of-scope)
-    -   [Generics will be checked when defined](#generics-will-be-checked-when-defined)
-    -   [Specialization strategy](#specialization-strategy)
+    -   [Checked generics will be checked when defined](#checked-generics-will-be-checked-when-defined)
+    -   [Implementation strategy](#implementation-strategy)
 -   [References](#references)
 
 <!-- tocstop -->
@@ -62,7 +61,8 @@ Carbon's checked generics will feature
 [early type checking](terminology.md#early-versus-late-type-checking) and
 [complete definition checking](terminology.md#complete-definition-checking).
 
-Carbon's template generics, in contrast, will more closely follow the
+Carbon's [template generics](#templates), in contrast, will more closely follow
+the
 [compile-time duck typing](https://en.wikipedia.org/wiki/Duck_typing#Templates_or_generic_types)
 approach of C++ templates.
 
@@ -105,7 +105,7 @@ languages:
     (compile-time only)
 -   [Abstract base classes](<https://en.wikipedia.org/wiki/Class_(computer_programming)#Abstract_and_concrete>)
     in C++, etc. (run-time only)
--   [Go interfaces](https://gobyexample.com/interfaces) (run-time only)
+-   [Go interfaces](https://gobyexample.com/interfaces)
 
 In addition to specifying the methods available on a type, we may in the future
 expand the role of interfaces to allow other type constraints, such as on size,
@@ -116,7 +116,7 @@ instead of, rather than in addition to, standard inheritance-and-classes
 object-oriented language support. For the moment, everything beyond specifying
 the _methods_ available is out of scope.
 
-### Relationship to templates
+## Templates
 
 The entire idea of statically typed languages is that coding against specific
 types and interfaces is a better model and experience. Unfortunately, templates
@@ -124,37 +124,37 @@ don't provide many of those benefits to programmers until it's too late, when
 users are consuming the API. Templates also come with high overhead, such as
 [template error messages](#better-compiler-experience).
 
-We want Carbon code to move towards more rigorously type checked constructs.
+We want Carbon code to move towards more rigorously type-checked constructs.
 However, existing C++ code is full of unrestricted usage of compile-time
 duck-typed templates. They are incredibly convenient to write and so likely will
 continue to exist for a long time.
 
-The question of whether Carbon has direct support for templates is out of scope
-for this document. The generics design is not completely separate from
-templates, so it is written as if Carbon will have its own templating system. It
-is assumed to be similar to C++ templates with some specific changes:
+Carbon will have direct support for templates in addition to checked generics.
+Carbon's template system will be similar to C++ templates with some specific
+changes:
 
--   It may have some limitations to be more compatible with generics, much like
-    how we
-    [restrict overloading](#generics-instead-of-open-overloading-and-adl).
+-   It may have some limitations to be more compatible with checked generics,
+    much like how we
+    [restrict overloading](#checked-generics-instead-of-open-overloading-and-adl).
 -   We likely will have a different method of selecting between different
     template instantiations, since
     [SFINAE](https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error)
     makes it difficult to deliver high quality compiler diagnostics.
 
-We assume Carbon will have templates for a few different reasons:
+Other aspects of Carbon will reduce the number of situations where errors will
+only be detected after the template is
+[instantiated](terminology.md#instantiation):
 
--   Carbon generics will definitely have to interact with _C++_ templates, and
-    many of the issues will be similar.
--   We want to leave room in the design for templates, since it seems like it
-    would be easier to remove templates if they are not pulling their weight
-    than figure out how to add them in if they turn out to be needed.
--   We may want to have templates in Carbon as a temporary measure, to make it
-    easier for users to transition off of C++ templates.
+-   Carbon's grammar won't require type information to disambiguate parsing, and
+    so definitions may be parsed without knowing the values of template
+    arguments.
+-   Carbon's name resolution is more restricted. Every package has its own
+    namespace, and there will be no
+    [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl).
 
-## Goals
+## Checked-generic goals
 
-Our goal for generics support in Carbon is to get most of the expressive
+Our goal for checked generics support in Carbon is to get most of the expressive
 benefits of C++ templates and open overloading with fewer downsides.
 Additionally, we want to support some dynamic dispatch use cases; for example,
 in cases that inheritance struggles with.
@@ -162,7 +162,7 @@ in cases that inheritance struggles with.
 ### Use cases
 
 To clarify the expressive range we are aiming for, here are some specific use
-cases we expect Carbon generics to cover.
+cases we expect Carbon checked generics to cover.
 
 #### Generic programming
 
@@ -183,18 +183,19 @@ generally be used with [static dispatch](#dispatch-control).
 
 #### Upgrade path from C++ abstract interfaces
 
-Interfaces in C++ are often represented by abstract base classes. Generics
-should offer an alternative that does not rely on inheritance. This means looser
-coupling and none of the problems of multiple inheritance. Some people, such as
+Interfaces in C++ are often represented by abstract base classes. Checked
+generics should offer an alternative that does not rely on inheritance. This
+means looser coupling and none of the problems of multiple inheritance. Some
+people, such as
 [Sean Parent](https://sean-parent.stlab.cc/papers-and-presentations/#better-code-runtime-polymorphism),
 advocate for runtime polymorphism patterns in C++ that avoid inheritance because
 it can cause runtime performance, correctness, and code maintenance problems in
 some situations. Those patterns require a lot of boilerplate and complexity in
 C++. It would be nice if those patterns were simpler to express with Carbon
-generics. More generally, Carbon generics will provide an alternative for those
-situations inheritance doesn't handle as well. As a specific example, we would
-like Carbon generics to supplant the need to support multiple inheritance in
-Carbon.
+checked generics. More generally, Carbon checked generics will provide an
+alternative for those situations inheritance doesn't handle as well. As a
+specific example, we would like Carbon checked generics to supplant the need to
+support multiple inheritance in Carbon.
 
 This is a case that would use [dynamic dispatch](#dispatch-control).
 
@@ -202,15 +203,16 @@ This is a case that would use [dynamic dispatch](#dispatch-control).
 
 Types which only support subclassing for test stubs and mocks, as in
 ["dependency injection"](https://en.wikipedia.org/wiki/Dependency_injection),
-should be able to easily migrate to generics. This extends outside the realm of
-testing, allowing general configuration of how dependencies can be satisfied.
-For example, generics might be used to configure how a library writes logs.
+should be able to easily migrate to checked generics. This extends outside the
+realm of testing, allowing general configuration of how dependencies can be
+satisfied. For example, checked generics might be used to configure how a
+library writes logs.
 
 This would allow you to avoid the runtime overhead of virtual functions, using
 [static dispatch](#dispatch-control) without the
 [poor build experience of templates](#better-compiler-experience).
 
-#### Generics instead of open overloading and ADL
+#### Checked generics instead of open overloading and ADL
 
 One name lookup problem we would like to avoid is caused by open overloading.
 Overloading is where you provide multiple implementations of a function with the
@@ -226,20 +228,22 @@ function was originally defined. Together these enable
 This is commonly used to provide a type-specific implementation of some
 operation, but doesn't provide any enforcement of consistency across the
 different overloads. It makes the meaning of code dependent on which overloads
-are imported, and is at odds with being able to type check a function
-generically.
+are imported, and is at odds with being able to type check a function's
+definition before instantiation.
 
 Our goal is to address this use case, known more generally as
 [the expression problem](https://eli.thegreenplace.net/2016/the-expression-problem-and-its-solutions),
-with a generics mechanism that does enforce consistency so that type checking is
-possible without seeing all implementations. This will be Carbon's replacement
-for open overloading. As a consequence, Carbon generics will need to be able to
-support operator overloading.
+with a checked-generics mechanism that does enforce consistency so that type
+checking is possible without seeing all implementations. This will be Carbon's
+replacement for open overloading. This is encapsulated in Carbon's
+["one static open extension mechanism" principle](/docs/project/principles/static_open_extension.md).
+As a consequence, Carbon checked generics will need to be able to support
+operator overloading.
 
 A specific example is the absolute value function `Abs`. We would like to write
 `Abs(x)` for a variety of types. For some types `T`, such as `Int32` or
 `Float64`, the return type will be the same `T`. For other types, such as
-`Complex64` or `Quaternion`, the return type will be different. The generic
+`Complex64` or `Quaternion`, the return type will be different. Checked generic
 functions that call `Abs` will need a way to specify whether they only operate
 on `T` such that `Abs` has signature `T -> T`.
 
@@ -250,14 +254,14 @@ overloading, which will
 ### Performance
 
 For any real-world C++ template, there shall be an idiomatic reformulation in
-Carbon generics that has equal or better performance.
+Carbon checked generics that has equal or better performance.
 [Performance is the top priority for Carbon](/docs/project/goals.md#performance-critical-software),
-and we expect to use generics pervasively, and so they can't compromise that
-goal in release builds.
+and we expect to use checked generics pervasively, and so they can't compromise
+that goal in release builds.
 
 **Nice to have:** There are cases where we should aim to do better than C++
-templates. For example, the additional structure of generics should make it
-easier to reduce generated code duplication, reducing code size and cache
+templates. For example, the additional structure of checked generics should make
+it easier to reduce generated code duplication, reducing code size and cache
 misses.
 
 ### Better compiler experience
@@ -266,12 +270,13 @@ Compared to C++ templates, we expect to reduce build times, particularly in
 development builds. We also expect the compiler to be able to report clearer
 errors, and report them earlier in the build process.
 
-One source of improvement is that the bodies of generic functions and types can
-be type checked once when they are defined, instead of every time they are used.
-This is both a reduction in the total work done, and how errors can be reported
-earlier. On use, the errors can be a lot clearer since they will be of the form
-"argument did not satisfy function's contract as stated in its signature"
-instead of "substitution failed at this line of the function's implementation."
+One source of improvement is that the bodies of checked generic functions and
+types can be type checked once when they are defined, instead of every time they
+are used. This is both a reduction in the total work done, and how errors can be
+reported earlier. On use, the errors can be a lot clearer since they will be of
+the form "argument did not satisfy function's contract as stated in its
+signature" instead of "substitution failed at this line of the function's
+implementation."
 
 **Nice to have:** In development builds, we will have the option of using
 [dynamic dispatch](#dispatch-control) to reduce build times. We may also be able
@@ -284,31 +289,30 @@ arguments or identical implementations and only generating code for them once.
 With a template, the implementation is part of the interface and types are only
 checked when the function is called and the template is instantiated.
 
-A generic function is type checked when it is defined, and type checking can't
-use any information that is only known when the function is instantiated such as
-the exact argument types. Furthermore, calls to a generic function may be type
-checked using only its declaration, not its body. You should be able to call a
-generic function using only a forward declaration.
+A checked-generic function is type checked when it is defined, and type checking
+can't use any information that is only known when the function is instantiated
+such as the exact argument types. Furthermore, calls to a checked-generic
+function may be type checked using only its declaration, not its body.
 
 ### Predictability
 
-A general property of generics is they are more predictable than templates. They
-make clear when a type satisfies the requirements of a function; they have a
-documented contract. Further, that contract is enforced by the compiler, not
-sensitive to implementation details in the function body. This eases evolution
-by reducing (but not eliminating) the impact of
+A general property of checked generics is they are more predictable than
+templates. They make clear when a type satisfies the requirements of a function;
+they have a documented contract. Further, that contract is enforced by the
+compiler, not sensitive to implementation details in the function body. This
+eases evolution by reducing (but not eliminating) the impact of
 [Hyrum's law](https://www.hyrumslaw.com/).
 
 **Nice to have:** We also want well-defined boundaries between what is legal and
 not. This is "will my code be accepted by the compiler" predictability. We would
 prefer to avoid algorithms in the compiler with the form "run for up to N steps
 and report an error if it isn't resolved by then." For example, C++ compilers
-will typically have a template recursion limit. With generics, these problems
-arise due to trying to reason whether something is legal in all possible
-instantiations, rather than with specific, concrete types.
+will typically have a template recursion limit. With checked generics, these
+problems arise due to trying to reason whether something is legal in all
+possible instantiations, rather than with specific, concrete types.
 
 Some of this is likely unavoidable or too costly to avoid, as most existing
-generics systems
+checked generics systems
 [have undecidable aspects to their type system](https://3fx.ch/typing-is-hard.html),
 including [Rust](https://sdleffler.github.io/RustTypeSystemTuringComplete/) and
 [Swift](https://forums.swift.org/t/swift-type-checking-is-undecidable/39024). We
@@ -343,13 +347,13 @@ we should invest in putting the proof search into IDEs or other tooling.
 Enable simple user control of whether to use dynamic or static dispatch.
 
 **Implementation strategy:** There are two strategies for generating code for
-generic functions:
+checked-generic functions:
 
--   Static specialization strategy: Like template parameters, the values for
-    generic parameters must be statically known at the callsite, or known to be
-    a generic parameter to the calling function. This can generate separate,
-    specialized versions of each combination of generic and template arguments,
-    in order to optimize for those types or values.
+-   Static strategy: Like template parameters, the values for checked parameters
+    must be statically known at the callsite, or known to be a generic parameter
+    to the calling function. This can generate separate, specialized versions of
+    each combination of checked and template arguments, in order to optimize for
+    those types or values.
 -   Dynamic strategy: This is when the compiler generates a single version of
     the function that uses runtime dispatch to get something semantically
     equivalent to separate instantiation, but likely with different size, build
@@ -363,17 +367,17 @@ code analysis, specific features used in the code, or profiling -- maybe some
 specific specializations are needed for performance, but others would just be
 code bloat.
 
-We require that all generic functions can be compiled using the static
-specialization strategy. For example, the values for generic parameters must be
+We require that all checked generic functions can be compiled using the static
+specialization strategy. For example, the values for checked parameters must be
 statically known at the callsite. Other limitations are
-[listed below](#specialization-strategy).
+[listed below](#implementation-strategy).
 
-**Nice to have:** It is desirable that the majority of functions with generic
+**Nice to have:** It is desirable that the majority of functions with checked
 parameters also support the dynamic strategy. Specific features may prevent the
 compiler from using the dynamic strategy, but they should ideally be relatively
 rare, and easy to identify. Language features should avoid making it observable
 whether function code generated once or many times. For example, you should not
-be able to take the address of a function with generic parameters, or determine
+be able to take the address of a function with checked parameters, or determine
 if a function was instantiated more than once using function-local static
 variables.
 
@@ -382,12 +386,14 @@ limit the extent it is used automatically by implementations. For example, the
 following features would benefit substantially from guaranteed monomorphization:
 
 -   Field packing in class layout. For example, packing a `bool` into the lower
-    bits of a pointer, or packing bit-fields with generic widths.
+    bits of a pointer, or packing bit-fields with checked-parameter widths.
 -   Allocating local variables in stack storage. Without monomorphization, we
     would need to perform dynamic memory allocation -- whether on the stack or
-    the heap -- for local variables whose sizes depend on generic parameters.
+    the heap -- for local variables whose sizes depend on checked parameters.
 -   Passing parameters to functions. We cannot pass values of generic types in
     registers.
+-   Finding [specialized](terminology.md#specialization) implementations of
+    interfaces beyond those clearly needed from the function signature.
 
 While it is possible to address these with dynamic dispatch, handling some of
 them might have far-reaching and surprising performance implications. We don't
@@ -407,53 +413,50 @@ acceptable even when running a development or debug build.
 ### Upgrade path from templates
 
 We want there to be a natural, incremental upgrade path from templated code to
-generic code.
-[Assuming Carbon will support templates directly](#relationship-to-templates),
-the first step of migrating C++ template code would be to first convert it to a
-Carbon template. The problem is then how to convert templates to generics within
-Carbon. This gives us these sub-goals:
-
--   Users should be able to convert a single template parameter to be generic at
-    a time. A hybrid function with both template and generic parameters has all
+checked-generic code. The first step of migrating C++ template code would be to
+first convert it to a [Carbon template](#templates). The problem is then how to
+convert templates to checked generics within Carbon. This gives us these
+sub-goals:
+
+-   Users should be able to convert a single template parameter to be checked at
+    a time. A hybrid function with both template and checked parameters has all
     the limitations of a template function: it can't be completely definition
     checked, it can't use the dynamic strategy, etc. Even so, there are still
     benefits from enforcing the function's declared contract for those
     parameters that have been converted.
--   Converting from a template parameter to a generic parameter should be safe.
+-   Converting from a template parameter to a checked parameter should be safe.
     It should either work or fail to compile, never silently change semantics.
 -   We should minimize the effort to convert functions and types from templated
-    to generic. Ideally it should just require specifying the type constraints,
+    to checked. Ideally it should just require specifying the type constraints,
     affecting just the signature of the function, not its body.
--   **Nice to have:** It should be legal to call templated code from generic
-    code when it would have the same semantics as if called from non-generic
-    code, and an error otherwise. This is to allow more templated functions to
-    be converted to generics, instead of requiring them to be converted
-    specifically in bottom-up order.
--   **Nice to have:** Provide a way to migrate from a template to a generic
-    without immediately updating all of the types used with the template. For
-    example, if the generic code requires types to implement a new interface,
-    one possible solution would use the original template code to provide an
-    implementation for that interface for any type that structurally has the
-    methods used by the original template.
-
-If Carbon does not end up having direct support for templates, the transition
-will necessarily be less incremental.
+-   **Nice to have:** It should be legal to call templated code from
+    checked-generic code when it would have the same semantics as if called from
+    non-generic code, and an error otherwise. This is to allow more templated
+    functions to be converted to checked generics, instead of requiring them to
+    be converted specifically in bottom-up order.
+-   **Nice to have:** Provide a way to migrate from a template to a checked
+    generic without immediately updating all of the types used with the
+    template. For example, if the checked-generic code requires types to
+    implement a new interface, one possible solution would use the original
+    template code to provide an implementation for that interface for any type
+    that structurally has the methods used by the original template.
 
 ### Path from regular functions
 
-Replacing a regular, non-parameterized function with a generic function should
-not affect existing callers of the function. There may be some differences, such
-as when taking the address of the function, but ordinary calls should not see
-any difference. In particular, the return type of a generic function should
-match, without any type erasure or additional named members.
+Replacing a regular, non-parameterized function with a checked-generic function
+should not affect existing callers of the function. There may be some
+differences, such as when taking the address of the function, but ordinary calls
+should not see any difference. In particular, the return type of a
+checked-generic function should match, without any type erasure or additional
+named members.
 
 ### Coherence
 
 We want the generics system to have the
 [_coherence_ property](terminology.md#coherence), so that the implementation of
-an interface for a type is well defined. Since a generic function only depends
-on interface implementations, they will always behave consistently on a given
-type, independent of context. For more on this, see
+an interface for a type is well defined. Since a checked-generic function only
+depends on interface implementations, they will always behave consistently on a
+given type, independent of context. For more on this, see
 [this description of what coherence is and why Rust enforces it](https://github.com/Ixrec/rust-orphan-rules#what-is-coherence).
 
 Coherence greatly simplifies the language design, since it reduces the need for
@@ -479,7 +482,7 @@ cases remain:
 -   They should be some way of selecting between multiple implementations of an
     interface for a given type. For example, a _Song_ might support multiple
     orderings, such as by title or by artist. These would be represented by
-    having multiple implementations of a _Comparable_ interface.
+    having multiple implementations of a _Ordered_ interface.
 -   In order to allow libraries to be composed, there must be some way of saying
     a type implements an interface that is in another package that the authors
     of the type were unaware of. This is especially important since the library
@@ -490,7 +493,7 @@ We should have some mechanism for addressing these use cases. There are multiple
 approaches that could work:
 
 -   Interface implementations could be external to types and are passed in to
-    generic functions separately.
+    checked-generic functions separately.
 -   There could be some way to create multiple types that are compatible with a
     given value that you can switch between using casts to select different
     interface implementations. This is the approach used by Rust
@@ -518,14 +521,15 @@ the definition of `T`.
 
 ### Learn from others
 
-Many languages have implemented generics systems, and we should learn from those
-experiences. We should copy what works and makes sense in the context of Carbon,
-and change decisions that led to undesirable compromises. We are taking the
-strongest guidance from Rust and Swift, which have similar goals and significant
-experience with the implementation and usability of generics. They both use
-nominal interfaces, were designed with generics from the start, and produce
-native code. Contrast with Go which uses structural interfaces, or Java which
-targets a virtual machine that predated its generics feature.
+Many languages have implemented checked-generics systems, and we should learn
+from those experiences. We should copy what works and makes sense in the context
+of Carbon, and change decisions that led to undesirable compromises. We are
+taking the strongest guidance from Rust and Swift, which have similar goals and
+significant experience with the implementation and usability of checked
+generics. They both use nominal interfaces, were designed with checked generics
+from the start, and produce native code. Contrast with Go which uses structural
+interfaces, or Java which targets a virtual machine that predated its generics
+feature.
 
 For example, Rust has found that supporting defaults for interface methods is a
 valuable feature. It is useful for [evolution](#interop-and-evolution),
@@ -559,8 +563,8 @@ interface, even if those methods happen to have the same signature.
 ### Interop and evolution
 
 [Evolution is a high priority for Carbon](/docs/project/goals.md#software-and-language-evolution),
-and so will need mechanisms to support evolution when using generics. New
-additions to an interface might:
+and so will need mechanisms to support evolution when using checked generics.
+New additions to an interface might:
 
 -   need default implementations
 -   be marked "upcoming" to allow for a period of transition
@@ -607,47 +611,39 @@ to work from C++, and Carbon functions could use that interface to invoke `swap`
 on C++ types.
 
 Similarly, we will want some way to implement Carbon interfaces for C++ types.
-For example, we might have a template implementation of an `Addable` interface
+For example, we might have a template implementation of an `AddWith` interface
 for any C++ type that implements `operator+`.
 
-## What we are not doing
+## What we are not doing with checked generics
 
-What are we **not** doing with generics, particularly things that some other
-languages do?
+What are we **not** doing with checked generics, particularly things that some
+other languages do?
 
 ### Not the full flexibility of templates
 
-Generics don't need to provide full flexibility of C++ templates:
+Checked generics don't need to provide full flexibility of C++ templates:
 
--   The current assumption is that
-    [Carbon templates](#relationship-to-templates) will cover those cases that
-    don't fit inside generics, such as code that relies on compile-time duck
-    typing.
+-   [Carbon templates](#templates) will cover those cases that don't fit inside
+    checked generics, such as code that relies on compile-time duck typing.
 -   We won't allow a specialization of some generic interface for some
     particular type to actually expose a _different_ interface, with different
     methods or different types in method signatures. This would break modular
     type checking.
 -   [Template metaprogramming](https://en.wikipedia.org/wiki/Template_metaprogramming)
-    will not be supported by Carbon generics. We expect to address those use
-    cases with metaprogramming or templates in Carbon.
-
-### Template use cases that are out of scope
+    will not be supported by Carbon checked generics. We expect to address those
+    use cases with metaprogramming or [templates](#templates) in Carbon.
+-   [Expression templates](https://en.wikipedia.org/wiki/Expression_templates)
+    are out of scope. It may be possible to express this approach in Carbon's
+    checked-generics system, but they won't drive any accommodation in the
+    checked-generics design.
 
-We will also not require Carbon generics to support
-[expression templates](https://en.wikipedia.org/wiki/Expression_templates),
-[variadics](https://en.wikipedia.org/wiki/Variadic_function), or
-[variadic templates](https://en.wikipedia.org/wiki/Variadic_template). Those are
-all out of scope. It would be fine for our generics system to support these
-features, but they won't drive any accommodation in the generics design, at
-least until we have some resolution about templates in Carbon.
-
-### Generics will be checked when defined
+### Checked generics will be checked when defined
 
 C++ compilers must defer full type checking of templates until they are
-instantiated by the user. Carbon will not defer type checking of generic
+instantiated by the user. Carbon will not defer type checking of checked-generic
 definitions.
 
-### Specialization strategy
+### Implementation strategy
 
 We want all generic Carbon code to support [static dispatch](#dispatch-control).
 This means we won't support unbounded type families. Unbounded type families are
@@ -656,7 +652,7 @@ when recursion creates an infinite collection of types, such as in
 or:
 
 ```carbon
-fn Sort[T:! Comparable](list: List(T)) -> List(T) {
+fn Sort[T:! Ordered](list: List(T)) -> List(T) {
   if (list.size() == 1) return list;
   var chunks: List(List(T)) = FormChunks(list, sqrt(list.size()));
   chunks = chunks.ApplyToEach(Sort);
@@ -665,15 +661,14 @@ fn Sort[T:! Comparable](list: List(T)) -> List(T) {
 }
 ```
 
-This, given an implementation of `Comparable` for any list with elements that
-are themselves `Comparable`, would recursively call itself to produce a set of
-types without bound. That is, calling `Sort` on a `List(Int)` would internally
-call `Sort` on a `List(List(Int))` and so on recursively without any static
-limit.
+This, given an implementation of `Ordered` for any list with elements that are
+themselves `Ordered`, would recursively call itself to produce a set of types
+without bound. That is, calling `Sort` on a `List(Int)` would internally call
+`Sort` on a `List(List(Int))` and so on recursively without any static limit.
 
-We won't require all generic Carbon code to support dynamic dispatch, but we
-would like it to be an implementation option for the compiler in the majority of
-cases.
+We won't require all checked-generic Carbon code to support dynamic dispatch,
+but we would like it to be an implementation option for the compiler in the
+majority of cases.
 
 Lastly, runtime specialization is out of scope as an implementation strategy.
 That is, some language runtimes JIT a specialization when it is first needed,
@@ -681,5 +676,8 @@ but it is not a goal for Carbon to support such an implementation strategy.
 
 ## References
 
+Proposals:
+
 -   [#24: Generics goals](https://github.com/carbon-language/carbon-lang/pull/24)
 -   [#950: Generic details 6: remove facets](https://github.com/carbon-language/carbon-lang/pull/950)
+-   [#2138: Checked and template generic terminology](https://github.com/carbon-language/carbon-lang/pull/2138)

+ 1 - 1
proposals/p2274.md

@@ -55,7 +55,7 @@ Interfaces are Carbon's
 [only static open extension mechanism](/docs/project/principles/static_open_extension.md),
 so user-defined indexing must be defined in terms of interfaces. In order to
 support
-[definition checking of generic functions](/docs/design/generics/goals.md#generics-will-be-checked-when-defined),
+[definition checking of generic functions](/docs/design/generics/goals.md#checked-generics-will-be-checked-when-defined),
 it must be possible to fully typecheck indexing operations using only the
 information exposed by those interfaces. And in order to provide
 [coherence](/docs/design/generics/goals.md#coherence), a given indexing