Преглед изворни кода

Reduce ambiguity in terminology (#3162)

Change terminology away from terms that are ambiguous:

- Reserve "generic type" for types with (compile-time) parameters, like
`Vector` in `Vector(T:! type)`. Don't use that term to refer to `T`, as
it would with
[#2360](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p2360.md#terminology).
- Use the term "compile-time" instead of "constant" to mean "template or
symbolic." Expand the term "constant" to include values, such as from
`let` bindings.
josh11b пре 2 година
родитељ
комит
9600030a05
4 измењених фајлова са 205 додато и 42 уклоњено
  1. 23 18
      docs/design/README.md
  2. 1 1
      docs/design/expressions/member_access.md
  3. 24 23
      docs/design/generics/terminology.md
  4. 157 0
      proposals/p3162.md

+ 23 - 18
docs/design/README.md

@@ -29,7 +29,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
         -   [String literals](#string-literals)
 -   [Values, objects, and expressions](#values-objects-and-expressions)
     -   [Expression categories](#expression-categories)
-    -   [Value phases](#value-phases)
+    -   [Expression phases](#expression-phases)
 -   [Composite types](#composite-types)
     -   [Tuples](#tuples)
     -   [Struct types](#struct-types)
@@ -399,7 +399,7 @@ Some values, such as `()` and `{}`, may even be used as types, but only act like
 types when they are in a type position, like after a `:` in a variable
 declaration or the return type after a `->` in a function declaration. Any
 expression in a type position must be
-[a constant or symbolic value](#value-phases) so the compiler can resolve
+[a compile-time constant](#expression-phases) so the compiler can resolve
 whether the value can be used as a type. This also puts limits on how much
 operators can do different things for types. This is good for consistency, but
 is a significant restriction on Carbon's design.
@@ -688,18 +688,18 @@ The primitive conversion steps used are:
 > -   Proposal
 >     [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)
 
-### Value phases
+### Expression phases
 
-Value expressions are also broken down into three _value phases_:
+Value expressions are further broken down into three _expression phases_:
 
--   A _constant_ has a value known at compile time, and that value is available
-    during type checking, for example to use as the size of an array. These
-    include literals ([integer](#integer-literals),
+-   A _template constant_ has a value known at compile time, and that value is
+    available during type checking, for example to use as the size of an array.
+    These include literals ([integer](#integer-literals),
     [floating-point](#floating-point-literals), [string](#string-literals)),
     concrete type values (like `f64` or `Optional(i32*)`), expressions in terms
     of constants, and values of
     [`template` parameters](#checked-and-template-parameters).
--   A _symbolic value_ has a value that will be known at the code generation
+-   A _symbolic constant_ has a value that will be known at the code generation
     stage of compilation when
     [monomorphization](https://en.wikipedia.org/wiki/Monomorphization) happens,
     but is not known during type checking. This includes
@@ -707,19 +707,23 @@ Value expressions are also broken down into three _value phases_:
     expressions with checked-generic arguments, like `Optional(T*)`.
 -   A _runtime value_ has a dynamic value only known at runtime.
 
-Carbon will automatically convert a constant to a symbolic value, or any value
-to a runtime value:
+Template constants together with symbolic constants are referred to as
+_compile-time constants_.
+
+Carbon will automatically convert a template constant to a symbolic constant, or
+any value to a runtime value:
 
 ```mermaid
 graph TD;
-    A(constant)-->B(symbolic value)-->C(runtime value);
+    A(template constant)-->B(symbolic constant)-->C(runtime value);
     D(reference expression)-->C;
 ```
 
-Constants convert to symbolic values and to runtime values. Symbolic values will
-generally convert into runtime values if an operation that inspects the value is
-performed on them. Runtime values will convert into constants or to symbolic
-values if constant evaluation of the runtime expression succeeds.
+Template constants convert to symbolic constants and to runtime values. Symbolic
+constants will generally convert into runtime values if an operation that
+inspects the value is performed on them. Runtime values will convert into
+template or symbolic constants if constant evaluation of the runtime expression
+succeeds.
 
 > **Note:** Conversion of runtime values to other phases is provisional.
 
@@ -1006,7 +1010,7 @@ the program's correctness must not depend on which option the Carbon
 implementation chooses.
 
 A [generic binding](#checked-and-template-parameters) uses `:!` instead of a
-colon (`:`) and can only match [constant or symbolic values](#value-phases), not
+colon (`:`) and can only match [compile-time constant](#expression-phases), not
 run-time values.
 
 The keyword `auto` may be used in place of the type in a binding pattern, as
@@ -2723,8 +2727,9 @@ templates. Constraints can then be added incrementally, with the compiler
 verifying that the semantics stay the same. Once all constraints have been
 added, removing the word `template` to switch to a checked parameter is safe.
 
-The [value phase](#value-phases) of a checked parameter is a symbolic value
-whereas the value phase of a template parameter is constant.
+The [expression phase](#expression-phases) of a checked parameter is a symbolic
+constant whereas the expression phase of a template parameter is template
+constant.
 
 Although checked generics are generally preferred, templates enable translation
 of code between C++ and Carbon, and address some cases where the type checking

+ 1 - 1
docs/design/expressions/member_access.md

@@ -583,7 +583,7 @@ fn CallStaticMethod(c: C) {
 
   // ✅ OK
   let T:! type = C.Nested;
-  // ❌ Error: value of `:!` binding is not constant because it
+  // ❌ Error: value of `:!` binding is not compile-time because it
   // refers to local variable `c`.
   let U:! type = c.Nested;
 }

+ 24 - 23
docs/design/generics/terminology.md

@@ -63,8 +63,8 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
 Generally speaking, when we talk about _generics_, either
 [checked or template](#checked-versus-template-parameters), we are talking about
-generalizing some language construct by adding a compile-time parameter, called
-a _generic parameter_, to it. So:
+generalizing some language construct by adding a _compile-time parameter_, also
+called a _generic parameter_, to it. So:
 
 -   a _generic function_ is a function with at least one compile-time parameter,
     which could be an explicit argument to the function or
@@ -285,28 +285,28 @@ complete definition checking. This occurs for
 
 _Binding patterns_ associate a name with a type and a value. This is used to
 declare function parameters, in `let` and `var` declarations, as well as to
-declare [generic parameters](#generic-means-compile-time-parameterized). There
-are three kinds of binding patterns, corresponding to
-[the three value phases](/docs/design/README.md#value-phases):
+declare [compile-time parameters](#generic-means-compile-time-parameterized) for
+classes, interfaces, and so on. There are three kinds of binding patterns,
+corresponding to
+[the three expression phases](/docs/design/README.md#expression-phases):
 
 -   A _runtime binding pattern_ binds to a dynamic value at runtime, and is
     written using a `:`, as in `x: i32`.
--   A _symbolic constant binding pattern_ or _symbolic binding pattern_ binds to
-    a compile-time value that is not known when type checking, and is used to
-    declare [checked generic](#checked-versus-template-parameters) parameters.
-    These binding use `:!`, as in `T:! type`.
--   A _template constant binding pattern_ or _template binding pattern_ binds to
-    a compile-time value that is known when type checking, and is used to
-    declare [template](#checked-versus-template-parameters) parameters. These
-    bindings use the keyword `template` in addition to `:!`, as in
-    `template T:! type`.
+-   A _symbolic binding pattern_ binds to a compile-time value that is not known
+    when type checking, and is used to declare
+    [checked generic](#checked-versus-template-parameters) parameters. These
+    binding use `:!`, as in `T:! type`.
+-   A _template binding pattern_ binds to a compile-time value that is known
+    when type checking, and is used to declare
+    [template](#checked-versus-template-parameters) parameters. These bindings
+    use the keyword `template` in addition to `:!`, as in `template T:! type`.
 
 The last two binding patterns, which are about binding a compile-time value, are
-called _constant binding patterns_, and correspond to those binding patterns
+called _compile-time binding patterns_, and correspond to those binding patterns
 that use `:!`.
 
 The name being declared, which is the identifier to the left of the `:` or `:!`,
-is called a _binding_, or more specifically a _runtime binding_, _constant
+is called a _binding_, or more specifically a _runtime binding_, _compile-time
 binding_, _symbolic binding_, or _template binding_. The expression to the right
 defining the type of the binding pattern is called the _binding type
 expression_, a kind of [type expression](#type-expression). For example, in
@@ -368,10 +368,10 @@ cases, we are concerned with the type value after the implicit conversion.
 ## Facet binding
 
 We use the term _facet binding_ to refer to the name introduced by a
-[constant binding pattern](#bindings) (using `:!` with or without the `template`
-modifier) where the declared type is a [facet type](#facet-type). In the binding
-pattern `T:! Hashable`, `T` is a facet binding, and the value of `T` is a
-[facet](#facet).
+[compile-time binding pattern](#bindings) (using `:!` with or without the
+`template` modifier) where the declared type is a [facet type](#facet-type). In
+the binding pattern `T:! Hashable`, `T` is a facet binding, and the value of `T`
+is a [facet](#facet).
 
 ## Deduced parameter
 
@@ -848,9 +848,10 @@ that specifies an array bound might have an integer type.
 
 ## Type constraints
 
-Type constraints restrict which types are legal for generic parameters or
-associated facets. They help define semantics under which they should be called,
-and prevent incorrect calls.
+Type constraints restrict which types are legal for a
+[facet binding](#facet-binding), like a facet parameter or associated facet.
+They help define semantics under which they should be called, and prevent
+incorrect calls.
 
 In general there are a number of different type relationships we would like to
 express, for example:

+ 157 - 0
proposals/p3162.md

@@ -0,0 +1,157 @@
+# Reduce ambiguity in terminology
+
+<!--
+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/3162)
+
+<!-- toc -->
+
+## Table of contents
+
+-   [Abstract](#abstract)
+-   [Problem](#problem)
+-   [Background](#background)
+-   [Proposal](#proposal)
+-   [Details](#details)
+-   [Rationale](#rationale)
+-   [Alternatives considered](#alternatives-considered)
+
+<!-- tocstop -->
+
+## Abstract
+
+Change terminology away from terms that are ambiguous:
+
+-   Reserve "generic type" for types with (compile-time) parameters, like
+    `Vector` in `Vector(T:! type)`. Don't use that term to refer to `T`, as it
+    would with [#2360](/proposals/p2360.md#terminology).
+-   Use the term "compile-time" instead of "constant" to mean "template or
+    symbolic." Expand the term "constant" to include values, such as from `let`
+    bindings.
+
+## Problem
+
+Right now, the term "generic type" has two meanings. In this example:
+
+```
+class Vector(T:! type);
+```
+
+Both `Vector` and `T` could be called a "generic type." It would be much less
+confusing if one of those two would have a different name.
+
+Similarly, "constant" can currently mean multiple things:
+
+-   "evaluation at compile time," as in "constant evaluation"
+-   "not variable," as in `let` instead of `var`
+-   "non-mutating view," as in `const T*`
+
+In practice, this has resulted in confusion. For example, the term "constant
+bindings" doesn't include all `let` bindings, even though they are not variable
+bindings.
+
+## Background
+
+The two meanings of "generic type" come from:
+
+-   Proposal [#2360](/proposals/p2360.md#terminology) defines a generic type to
+    be a type or facet introduced by a `:!` binding, such as in a generic
+    parameter or associated constant.
+-   Other uses of the term generic, such as in generic function, mean a language
+    construct with a compile-time parameter (as in
+    [Rust](https://doc.rust-lang.org/rust-by-example/generics.html)). This is
+    the usage in the broader programming language community, and includes
+    calling parameterized types "generic types" (as in
+    [Java](https://docs.oracle.com/javase/tutorial/java/generics/types.html),
+    [.NET](https://learn.microsoft.com/en-us/dotnet/standard/generics/#terminology),
+    [Swift](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/generics/#Generic-Types)).
+
+Issue
+[#1391: New name for "constant" value phase](https://github.com/carbon-language/carbon-lang/issues/1391)
+implemented in proposal
+[#2964: Expression phase terminology](https://github.com/carbon-language/carbon-lang/pull/2964),
+expanded the term "constant" from referring to just template constants to also
+include symbolic constants from checked generics. Since then proposal
+[#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)
+introduced the `const` modifier on types, providing a read-only view.
+
+## Proposal
+
+We make these changes:
+
+-   Reserve "generic type" for types with (compile-time) parameters, like
+    `Vector` in `Vector(T:! type)`. Don't use that term to refer to `T`, as it
+    would with
+    [#2360](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p2360.md#terminology).
+-   Expand "constant binding" to include all `let` bindings.
+-   Use the term "compile-time binding" to refer to the collection of template
+    and symbolic bindings, such as from generic parameters and associated
+    constants.
+-   Similarly "compile-time constants" to refer to template and symbolic
+    constants, as opposed to just "constants."
+-   The term "compile-time parameter" may be used instead of "generic
+    parameter." For now, both terms will be used, but in the future it might be
+    clearer to only use "generic" to mean "has compile-time parameters."
+-   Only use "symbolic binding" and "template binding" not "symbolic constant
+    binding" nor "template constant binding."
+-   Where applicable, switch from talking about parameters to bindings, since
+    almost everything that applies to compile-time parameters also applies to
+    compile-time bindings. For example, see
+    ["binding patterns"](/docs/design/generics/terminology.md#bindings) and
+    ["facet binding"](/docs/design/generics/terminology.md#facet-binding) in the
+    generics terminology doc.
+
+## Details
+
+The following design documents have been updated in this proposal to reflect
+these changes:
+
+-   [Language design overview](/docs/design/README.md)
+-   [Generics terminology](/docs/design/generics/terminology.md)
+-   [Member access expressions](/docs/design/expressions/member_access.md)
+    **FIXME:** Need to sync with
+    [#3162](https://github.com/carbon-language/carbon-lang/pull/3162).
+
+Some of these changes have already been implemented in:
+
+-   [PR #3048: Update Generics terminology document](https://github.com/carbon-language/carbon-lang/pull/3048)
+-   [PR #3061: Update generics overview](https://github.com/carbon-language/carbon-lang/pull/3061)
+
+## Rationale
+
+This proposal advances these goals of Carbon:
+
+-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem):
+    Having clear and unambiguous terminology is important for making a precise
+    language specification and as well as other design and developer
+    documentation.
+-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):
+    particularly the sub-goal that "The behavior and semantics of code should be
+    clearly and simply specified whenever possible."
+
+## Alternatives considered
+
+The main alternative considered was the status quo. This was discussed:
+
+-   [starting 2023-Jul-14 in #naming](https://discord.com/channels/655572317891461132/963846118964350976/1129542605538074777)
+-   [2023-Jul-27 in open discussion](https://docs.google.com/document/d/1gnJBTfY81fZYvI_QXjwKk1uQHYBNHGqRLI2BS_cYYNQ/edit?resourcekey=0-ql1Q1WvTcDvhycf8LbA9DQ#heading=h.3tki3lncihf)
+-   [2023-Aug-28 in #naming](https://discord.com/channels/655572317891461132/963846118964350976/1145790947083423777)
+
+During those discussions, we also considered "symbolic type" instead of "generic
+type". This did not work out, though, since it conflicted with the term
+"symbolic" used as an expression phase. We considered other possibilities:
+"figurative type", "computed type", "hole type", "open type", and "placeholder
+type" (though that might be better applied to `auto`).
+
+It also came up that we did not want to use the term "generic binding" to mean a
+compile-time binding, because that term would be better applied to a
+parameterized binding, see
+[#naming on 2023-Jul-31](https://discord.com/channels/655572317891461132/963846118964350976/1135704682128494712).
+Those are not currently supported in Carbon, but are something we are likely to
+add. For example,
+[Rust has generic associated types](https://rust-lang.github.io/generic-associated-types-initiative/explainer/motivation.html)
+as of [v1.65](https://blog.rust-lang.org/2022/10/28/gats-stabilization.html).