Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

David's Feedback #1

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions P2676R0.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ author:
toc: false
---

<!-- DJS: Typically there's an abstract. Perhaps we could use something like the one I proposed
earlier this week? It should tell folks why they should pay attention to the paper.
-->

# Introduction

This paper presents a low-level programming model that is simple, powerful, efficient, and safe. We
Expand All @@ -26,7 +30,7 @@ Software safety is a growing and well-justified concern across government and in
recent [Linux foundation
plan](https://8112310.fs1.hubspotusercontent-na1.net/hubfs/8112310/OpenSSF/OSS%20Mobilization%20Plan.pdf)
specifically calling for “moving software away from C and C++ to safer languages.” Until now,
acheiving memory safety in a language like C++ has meant the use of impractical whole-program
achieving memory safety in a language like C++ has meant the use of impractical whole-program
analysis or the addition of hard-to-satisfy lifetime annotation requirements that significantly
increase API complexity. As an alternative, we present an object model—implemented in the [Val
research language](https://www.val-lang.dev/)—based on value semantics; an idea already deeply
Expand All @@ -40,13 +44,21 @@ once:
As the C++ committee considers its response to the safety crisis, understanding the Val model could
allow us to arrive at a safer C++ that is also simpler.

<!-- DJS: I'd suggest some motivating code snippets early in the paper, perhaps here. In particular,
it would be good to see C++ code side-by-side with how it is done in Val.
-->

# The Val Object Model

## Independence

The Val model starts by identifying **independence**—the idea that a mutation to one variable cannot
affect the value of another—as a key property of types with value semantics. Independence is the true
source of the benefits functional programmers attribute to strict immutability, and of Rust's
<!-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
DJS: I think this is a strawman argument. The key benefit is that it allows one to program using
traditional mathematics, that is immutable math.
-->
“fearless concurrency.”

C++ supports independence in three ways:
Expand Down Expand Up @@ -75,7 +87,7 @@ practice that we do it automatically, even though it affects semantics:

::: cmptable

### Before
### Before

```cpp
// Offsets x by 2*delta.
Expand All @@ -91,7 +103,7 @@ void main() {
}
```

### After
### After

```cpp
// Offsets x by 2*delta.
Expand All @@ -107,9 +119,13 @@ void main() {
}
```

<!-- DJS: The intent of 'cmptable' is to show a before/after table for a particular language
feature. I think using this in the way it is above will cause confusion.
-->

:::

The only reasonable way to make the *After* code correct is to add an aditional independence
The only reasonable way to make the *After* code correct is to add an additional independence
requirement, and hope that users uphold it.

```cpp
Expand Down Expand Up @@ -150,7 +166,7 @@ standard with the Law in mind, it is still easy to find cases like these:
int main() {
std::vector v = { 0, 1 };
std::ranges::sort(
v, [&v](int x, int y) {
v, [&v](int x, int y) {
v.push_back(2); return y < x;
});
}
Expand Down Expand Up @@ -286,14 +302,18 @@ The patterns that do not fit these defaults can be expressed by user annotations
We refer the interested reader to [@P1179R1] for the complete specification.

We note that the ownership discipline proposed by the C++ Core Guidelines upholds the Law of Exclusivity.
This observation strongly suggests that, alghouth relinquishing reference semantics is often met with reluctance, value independence is a requirement to guarantee memory safety scalably without unaffordable run-time costs.
This observation strongly suggests that, although relinquishing reference semantics is often met with reluctance, value independence is a requirement to guarantee memory safety scalably without unaffordable run-time costs.
The fact that other programming languages, such as Rust, Pony, and Verona have come to the same conclusion gives weight to this argument.

In Val, ownership is conveyed through whole/part relationships.
For example, a vector (i.e., a dynamic array in Val parlance parlance) is naturally a composition of its elements, which denotes its parts.
A whole is responsible for the lifetime of its parts, just like an owner is responsible for that of its owned objects.
Further, mutating a whole requires its independence, just like passing an owner as an argument prevents references to its contents to be passed simultaneously.

<!-- DJS: I think it would be helpful to see an example of a P1179R1 annotation and compare
that to what the equivalent would be in Val.
-->

Without first-class pointers and references, reasoning about whole/part relationships is sufficient to achieve similar expressiveness as ownership-based approaches, only without the complexity costs of an ad-hoc ownership model.
The definition of a whole is unambiguous in a world governed by mutable value semantics.
In contrast, the definition of an owner in a world of references is orthogonal and it incumbs to the user to teach the compiler or static analyzer about the distinctions between owners and non-owners.
Expand All @@ -305,6 +325,9 @@ Nonetheless, we are confident they can reach these goals through iterative refin
Val's safe subset is almost as expressive as Rust's.
The difference lies in the fact that one cannot reassign a binding or remote part (i.e., a reference in Rust) to a different object.
This limitation has very little impact in practice.
<!-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
DJS: ECREE
-->
Hence, using Rust as a proxy for a future more complete version of the C++ Core Guidlines, we can predict that Val's expressiveness is on par with the latter.

# Conclusion
Expand Down