Reduce ambiguity in terminology

Pull request

Table of contents

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.
  • 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 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). This is the usage in the broader programming language community, and includes calling parameterized types “generic types” (as in Java, .NET, Swift).

Issue #1391: New name for “constant” value phase implemented in proposal #2964: Expression phase terminology, 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 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.
  • 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” and “facet binding” in the generics terminology doc.

Details

The following design documents have been updated in this proposal to reflect these changes:

Some of these changes have already been implemented in:

Rationale

This proposal advances these goals of Carbon:

Alternatives considered

The main alternative considered was the status quo. This was discussed:

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. Those are not currently supported in Carbon, but are something we are likely to add. For example, Rust has generic associated types as of v1.65.