Browse Source

Disambiguate "value binding" (#6231)

This proposal removes the definition of the term "value binding" as a
primitive
category conversion from reference to value, replacing it with the term
"value
acquisition". The other meaning of "value binding", a binding declared
by a
value binding pattern, is unchanged.
Geoff Romer 6 months ago
parent
commit
39503a5561

+ 1 - 1
docs/design/README.md

@@ -702,7 +702,7 @@ similar to [C++](https://en.cppreference.com/w/cpp/language/value_category):
 Expressions in one category can be converted to any other category when needed.
 The primitive conversion steps used are:
 
--   _Value binding_ converts a reference expression into a value expression.
+-   _Value acquisition_ converts a reference expression into a value expression.
 -   _Direct initialization_ converts a value expression into an initializing
     expression.
 -   _Copy initialization_ converts a reference expression into an initializing

+ 23 - 22
docs/design/values.md

@@ -12,7 +12,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
 -   [Values, objects, and expressions](#values-objects-and-expressions)
     -   [Expression categories](#expression-categories)
-        -   [Value binding](#value-binding)
+        -   [Value acquisition](#value-acquisition)
         -   [Direct initialization](#direct-initialization)
         -   [Copy initialization](#copy-initialization)
         -   [Temporary materialization](#temporary-materialization)
@@ -80,8 +80,8 @@ There are three expression categories in Carbon:
 Expressions in one category can be converted to any other category when needed.
 The primitive conversion steps used are:
 
--   [_Value binding_](#value-binding) forms a value expression from the current
-    value of the object referenced by a reference expression.
+-   [_Value acquisition_](#value-acquisition) forms a value expression from the
+    current value of the object referenced by a reference expression.
 -   [_Direct initialization_](#direct-initialization) converts a value
     expression into an initializing expression.
 -   [_Copy initialization_](#copy-initialization) converts a reference
@@ -91,11 +91,11 @@ The primitive conversion steps used are:
 
 These conversion steps combine to provide the transitive conversion table:
 
-|               From: | value                     | reference | initializing       |
-| ------------------: | ------------------------- | --------- | ------------------ |
-|        to **value** | ==                        | bind      | materialize + bind |
-|    to **reference** | direct init + materialize | ==        | materialize        |
-| to **initializing** | direct init               | copy init | ==                 |
+|               From: | value                     | reference | initializing          |
+| ------------------: | ------------------------- | --------- | --------------------- |
+|        to **value** | ==                        | acquire   | materialize + acquire |
+|    to **reference** | direct init + materialize | ==        | materialize           |
+| to **initializing** | direct init               | copy init | ==                    |
 
 Reference expressions formed through temporary materialization are called
 [_ephemeral reference expressions_](#ephemeral-reference-expressions) and have
@@ -105,13 +105,14 @@ to declared storage are called
 restrictions on what is valid, there is no distinction in their behavior or
 semantics.
 
-#### Value binding
+#### Value acquisition
 
-We call forming a value expression from a reference expression _value binding_.
-This forms a value expression that will evaluate to the value of the object in
-the referenced storage of the reference expression. It may do this by eagerly
-reading that value into a machine register, lazily reading that value on-demand
-into a machine register, or in some other way modeling that abstract value.
+We call forming a value expression from a reference expression _value
+acquisition_. This forms a value expression that will evaluate to the value of
+the object in the referenced storage of the reference expression. It may do this
+by eagerly reading that value into a machine register, lazily reading that value
+on-demand into a machine register, or in some other way modeling that abstract
+value.
 
 See the [value expressions](#value-expressions) section for more details on the
 semantics of value expressions.
@@ -132,8 +133,8 @@ trivially and where this is implemented as a `memcpy` of their underlying bytes.
 #### Temporary materialization
 
 We use temporary materialization when we need to initialize an object by way of
-storage, but weren't provided dedicate storage and can simply bind the result to
-a value afterward.
+storage, but weren't provided dedicated storage and can simply acquire the
+result as a value afterward.
 
 > **Open question:** The lifetimes of temporaries is not yet specified.
 
@@ -235,7 +236,7 @@ occur, which will typically be marked by an open brace (`{`) and close brace
 
 ### Consuming function parameters
 
-Just as part of a `let` binding can use a `var` prefix to become a variable
+Just as part of a `let` declaration can use a `var` prefix to become a variable
 pattern and bind names that will form reference expressions to the variable's
 storage, so can function parameters:
 
@@ -338,11 +339,11 @@ enable generic code that needs a single type model that will have consistently
 good performance.
 
 When forming a value expression from a reference expression, Carbon
-[binds](#value-binding) the referenced object to that value expression. This
-allows immediately reading from the object's storage into a machine register or
-a copy if desired, but does not require that. The read of the underlying object
-can also be deferred until the value expression itself is used. Once an object
-is bound to a value expression in this way, any mutation to the object or its
+[acquires](#value-acquisition) the value of the referenced object. This allows
+immediately reading from the object's storage into a machine register or a copy
+if desired, but does not require that. The read of the underlying object can
+also be deferred until the value expression itself is used. Once an object is
+bound to a value expression in this way, any mutation to the object or its
 storage ends the lifetime of the value binding, and makes any use of the value
 expression an error.
 

+ 85 - 0
proposals/p6231.md

@@ -0,0 +1,85 @@
+# Disambiguate "value binding"
+
+<!--
+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/6231)
+
+<!-- toc -->
+
+## Table of contents
+
+-   [Abstract](#abstract)
+-   [Problem](#problem)
+-   [Proposal](#proposal)
+-   [Details](#details)
+-   [Rationale](#rationale)
+-   [Alternatives considered](#alternatives-considered)
+    -   [Rename "a binding declared by a value binding pattern"](#rename-a-binding-declared-by-a-value-binding-pattern)
+    -   [Other names for "primitive conversion from reference to value"](#other-names-for-primitive-conversion-from-reference-to-value)
+
+<!-- tocstop -->
+
+## Abstract
+
+This proposal removes the definition of the term "value binding" as a primitive
+category conversion from reference to value, replacing it with the term "value
+acquisition". The other meaning of "value binding", a binding declared by a
+value binding pattern, is unchanged.
+
+## Problem
+
+The design docs currently define "value binding" in two conflicting ways: it can
+mean the binding declared by a value binding pattern, or it can mean a primitive
+category conversion from reference to value. The two can usually be
+disambiguated based on context, but it's not always straightforward, and the
+double meaning complicates naming within the toolchain implementation.
+
+## Proposal
+
+This proposal removes the definition of the term "value binding" as a primitive
+category conversion from reference to value, replacing it with the term "value
+acquisition".
+
+## Details
+
+See the changes elsewhere in the
+[proposal PR](https://github.com/carbon-language/carbon-lang/pull/6231).
+
+## Rationale
+
+Using unambiguous terminology advances our
+[community and culture](/docs/project/goals.md#community-and-culture) goals, by
+facilitating clear communication.
+
+## Alternatives considered
+
+### Rename "a binding declared by a value binding pattern"
+
+We could instead rename the other meaning of "value binding", but that would be
+considerably more difficult because that meaning appears to be more common, and
+because it's part of a cluster of other heavily-used terms, such as "reference
+binding" and "binding pattern", which we would need to rename for consistency.
+
+### Other names for "primitive conversion from reference to value"
+
+We considered several alternative names before settling on "value acquisition":
+
+-   "Value borrowing" highlights the close analogy to Rust borrowing, which
+    similarly forbids mutation of the object for the lifetime of the borrow.
+    However, this naming choice somewhat prejudges the safety story for this
+    operation.
+-   "Value snapshotting" and "value observation" may not effectively communicate
+    the ongoing coupling between the object and the value.
+-   "Value capturing" reuses and extends the existing meaning of "capturing" in
+    lambdas. However, it may be confusing that a lambda can have value captures
+    that are not initialized by value capturing (for example because the
+    initializer is a value, not a reference).
+-   "Value expression conversion" is straightforward and hard to misunderstand.
+    However, we sometimes use "value binding" to refer to the _result_ of a
+    reference-to-value conversion, for example "the lifetime of a value
+    binding". "Value expression conversion" doesn't seem to lend itself to that
+    usage, possibly because it's too generic to be a recognizable term of art.

+ 1 - 1
toolchain/check/member_access.cpp

@@ -420,7 +420,7 @@ static auto PerformInstanceBinding(Context& context, SemIR::LocId loc_id,
             SemIR::ExprCategory::Value) {
       // Class element access on a value expression produces an ephemeral
       // reference if the class's value representation is a pointer to the
-      // object representation. Add a value binding in that case so that the
+      // object representation. Add a value acquisition in that case so that the
       // expression category of the result matches the expression category
       // of the base.
       access_id = ConvertToValueExpr(context, access_id);

+ 2 - 2
toolchain/lower/handle_expr_category.cpp

@@ -14,10 +14,10 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
   switch (context.GetValueRepr(inst_type).repr.kind) {
     case SemIR::ValueRepr::Unknown:
       CARBON_FATAL(
-          "Value binding for type with incomplete value representation");
+          "Value acquisition for type with incomplete value representation");
     case SemIR::ValueRepr::Dependent:
       CARBON_FATAL(
-          "Value binding for type with dependent value representation");
+          "Value acquisition for type with dependent value representation");
     case SemIR::ValueRepr::None:
       // Nothing should use this value, but StubRef needs a value to
       // propagate.

+ 2 - 2
toolchain/lower/testdata/class/value_access.carbon

@@ -15,9 +15,9 @@ class C {
 }
 
 fn F(c: C) -> i32 {
-  // TODO: `c.a` is a value expression here, which forces a value binding as
+  // TODO: `c.a` is a value expression here, which forces a value acquisition as
   // part of the member access, creating a tuple value temporary. We could
-  // defer performing the value binding to avoid creating this temporary.
+  // defer performing the value acquisition to avoid creating this temporary.
   return c.a.1;
 }
 

+ 3 - 2
toolchain/sem_ir/typed_insts.h

@@ -287,8 +287,9 @@ struct BindSymbolicName {
   InstId value_id;
 };
 
-// A value binding. Used when an expression contains a reference and we want a
-// value.
+// A value acquisition. Used when an expression contains a reference and we want
+// a value.
+// TODO: Rename to AcquireValue
 struct BindValue {
   static constexpr auto Kind =
       InstKind::BindValue.Define<Parse::NodeId>({.ir_name = "bind_value"});