mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 21:00:13 +01:00
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.
This commit is contained in:
@@ -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
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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"});
|
||||
|
||||
Reference in New Issue
Block a user