Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
9648270
Filling out template with PR 5434
josh11b May 6, 2025
a0b90c7
Checkpoint progress.
josh11b May 6, 2025
7cc4b32
Checkpoint progress.
josh11b May 12, 2025
bf4930f
Checkpoint progress.
josh11b May 16, 2025
cc0a1f3
Checkpoint progress.
josh11b May 16, 2025
eb2ab64
Checkpoint progress.
josh11b May 16, 2025
a71ba59
Checkpoint progress.
josh11b May 16, 2025
018dda5
Checkpoint progress.
josh11b May 16, 2025
cbacede
Checkpoint progress.
josh11b May 17, 2025
2d6a7a3
Checkpoint progress.
josh11b May 17, 2025
4a87f20
Checkpoint progress.
josh11b May 18, 2025
90d250e
Checkpoint progress.
josh11b May 18, 2025
8151bed
Checkpoint progress.
josh11b May 18, 2025
7172159
Checkpoint progress.
josh11b May 19, 2025
66a6f47
Checkpoint progress.
josh11b May 19, 2025
8060cf7
Checkpoint progress.
josh11b May 19, 2025
4b1584d
Checkpoint progress.
josh11b May 20, 2025
c89d46d
Ready for review
josh11b May 20, 2025
0894f68
Oops, missed a couple of final touches
josh11b May 20, 2025
79d6ddb
Merge remote-tracking branch 'upstream/trunk' into ref
josh11b May 20, 2025
acec7d9
Apply suggestions from code review
josh11b May 21, 2025
626c3ae
Updates inspired by review
josh11b May 21, 2025
319f5eb
Fix incorrect statement
josh11b May 21, 2025
28d8cc2
Changes in response to review
josh11b May 21, 2025
3570dc0
Update proposals/p5434.md
josh11b May 21, 2025
3f654fc
Move indexing changes to the relevant design doc
josh11b May 21, 2025
2a76c74
Incorporate more feedback
josh11b May 21, 2025
2915e39
typo
josh11b May 21, 2025
cf7d94e
Implement suggestion
josh11b May 21, 2025
4075aed
Add small section on completeness
josh11b May 21, 2025
3e13632
Title
josh11b May 22, 2025
0fdf298
Consider alternative category for `=>`
josh11b May 22, 2025
b8cd942
Add alternative
josh11b May 29, 2025
09c9455
Merge alternatives
josh11b May 29, 2025
00b06b0
Improve indexing
josh11b Jun 11, 2025
3abc014
Checkpoint progress.
josh11b Jun 13, 2025
769e122
BindToValue
josh11b Jun 13, 2025
72c79b2
Apply suggestions from code review
josh11b Jun 13, 2025
523022c
Address some feedback
josh11b Jun 13, 2025
a90a7af
Update proposals/p5434.md
josh11b Jun 17, 2025
24c736c
Checkpoint progress.
josh11b Jun 17, 2025
2aca8e8
Merge remote-tracking branch 'refs/remotes/origin/ref' into ref
josh11b Jun 17, 2025
0cac941
Checkpoint progress.
josh11b Jun 18, 2025
38f0f90
Checkpoint progress.
josh11b Jun 18, 2025
7e688a3
Checkpoint progress.
josh11b Jun 18, 2025
7787bd0
Checkpoint progress.
josh11b Jun 18, 2025
37b5c84
Checkpoint progress.
josh11b Jun 18, 2025
a11e69f
Checkpoint progress.
josh11b Jun 18, 2025
c8e37f3
`init`
josh11b Jun 18, 2025
eb1df53
Update custom value representation syntax to use `ref` keyword
josh11b Jul 1, 2025
9ec8a85
Add text to hopefully address confusion, as suggested in review
josh11b Jul 1, 2025
50417f4
Apply suggestions from code review
josh11b Jul 8, 2025
08f332b
Checkpoint progress.
josh11b Jul 8, 2025
1f5129a
Checkpoint progress.
josh11b Jul 20, 2025
90d4ec4
Implement suggestions
josh11b Jul 21, 2025
d14726d
Implement suggestions
josh11b Jul 21, 2025
cfe2a65
Apply suggestions from code review
josh11b Aug 1, 2025
3520180
Add TODO about updating initializing return docs
josh11b Aug 1, 2025
5aa00c7
Fix formatting
josh11b Aug 1, 2025
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
44 changes: 17 additions & 27 deletions docs/design/expressions/indexing.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,8 @@ implement that interface, or to method calls on `IndexWith` otherwise.
`IndirectIndexWith` provides a final blanket `impl` of `IndexWith`, so a type
can implement at most one of those two interfaces.

The `Addr` methods of these interfaces, which are used to form durable reference
expressions on indexing, must return a pointer and work similarly to the
[pointer dereference customization interface](/docs/design/values.md#dereferencing-customization).
The returned pointer is then dereferenced by the language to form the reference
expression referring to the pointed-to object. These methods must return a raw
pointer, and do not automatically chain with customized dereference interfaces.

**Open question:** It's not clear that the lack of chaining is necessary, and it
might be more expressive for the pointer type returned by the `Addr` methods to
be an associated facet with a default to allow types to produce custom
pointer-like types on their indexing boundary and have them still be
automatically dereferenced.
The `Ref` methods of these interfaces, which are used to form durable reference
expressions on indexing, must return by `ref`.

## Details

Expand All @@ -64,13 +54,13 @@ Its semantics are defined in terms of the following interfaces:
```
interface IndexWith(SubscriptType:! type) {
let ElementType:! type;
fn At[self: Self](subscript: SubscriptType) -> ElementType;
fn Addr[addr self: Self*](subscript: SubscriptType) -> ElementType*;
fn At[bound self: Self](subscript: SubscriptType) -> val ElementType;
fn Ref[bound ref self: Self](subscript: SubscriptType) -> ref ElementType;
}

interface IndirectIndexWith(SubscriptType:! type) {
require Self impls IndexWith(SubscriptType);
fn Addr[self: Self](subscript: SubscriptType) -> ElementType*;
fn Ref[bound self: Self](subscript: SubscriptType) -> ref ElementType;
}
```

Expand All @@ -79,11 +69,11 @@ rewritten based on the expression category of _lhs_ and whether `T` is known to
implement `IndirectIndexWith(I)`:

- If `T` implements `IndirectIndexWith(I)`, the expression is rewritten to
"`*((` _lhs_ `).(IndirectIndexWith(I).Addr)(` _index_ `))`".
"`(` _lhs_ `).(IndirectIndexWith(I).Ref)(` _index_ `)`".
- Otherwise, if _lhs_ is a
[_durable reference expression_](/docs/design/values.md#durable-reference-expressions),
the expression is rewritten to "`*((` _lhs_ `).(IndexWith(I).Addr)(` _index_
`))`".
the expression is rewritten to "`(` _lhs_ `).(IndexWith(I).Ref)(` _index_
`)`".
- Otherwise, the expression is rewritten to "`(` _lhs_ `).(IndexWith(I).At)(`
_index_ `)`".

Expand All @@ -93,18 +83,18 @@ implement `IndirectIndexWith(I)`:
final impl forall
[SubscriptType:! type, T:! IndirectIndexWith(SubscriptType)]
T as IndexWith(SubscriptType) {
let ElementType:! type = T.(IndirectIndexWith(SubscriptType)).ElementType;
fn At[self: Self](subscript: SubscriptType) -> ElementType {
return *(self.(IndirectIndexWith(SubscriptType).Addr)(index));
where ElementType = T.(IndirectIndexWith(SubscriptType).ElementType);
fn At[bound self: Self](subscript: SubscriptType) -> val ElementType {
return self.(IndirectIndexWith(SubscriptType).Ref)(index);
}
fn Addr[addr self: Self*](subscript: SubscriptType) -> ElementType* {
return self->(IndirectIndexWith(SubscriptType).Addr)(index);
fn Ref[bound ref self: Self](subscript: SubscriptType) -> ref ElementType {
return self.(IndirectIndexWith(SubscriptType).Ref)(index);
}
}
```

Thus, a type that implements `IndirectIndexWith` need not, and cannot, provide
its own definitions of `IndexWith.At` and `IndexWith.Addr`.
its own definitions of `IndexWith.At` and `IndexWith.Ref`.

### Examples

Expand All @@ -114,8 +104,8 @@ An array type could implement subscripting like so:
class Array(template T:! type) {
impl as IndexWith(like i64) {
let ElementType:! type = T;
fn At[self: Self](subscript: i64) -> T;
fn Addr[addr self: Self*](subscript: i64) -> T*;
fn At[bound self: Self](subscript: i64) -> val T;
fn Ref[bound ref self: Self](subscript: i64) -> ref T;
}
}
```
Expand All @@ -126,7 +116,7 @@ And a type such as `std::span` could look like this:
class Span(T:! type) {
impl as IndirectIndexWith(like i64) {
let ElementType:! type = T;
fn Addr[self: Self](subscript: i64) -> T*;
fn Ref[bound ref self: Self](subscript: i64) -> ref T;
}
}
```
Expand Down
25 changes: 17 additions & 8 deletions docs/design/values.md
Original file line number Diff line number Diff line change
Expand Up @@ -414,9 +414,9 @@ the available implementation strategies.
> **Future work:** The interaction between a
> [custom value representation](#value-representation-and-customization) and a
> value expression used with a polymorphic type needs to be fully captured.
> Either it needs to restrict to a `const Self*` style representation (to
> prevent slicing) or it needs to have a model for the semantics when a
> different value representation is used.
> Either it needs to restrict to a `const ref` style representation (to prevent
> slicing) or it needs to have a model for the semantics when a different value
> representation is used.

### Interop with C++ `const &` and `const` methods
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Commenting here since there's no better place for it)

If I understand correctly, the "Deferred initialization from values and references" section below is basically just saying that the compiler can rewrite -> Foo to -> let Foo if that would be safe and correct (see also discussion here). If so, it would be nice to say so explicitly, and remove or relocate all the verbiage that amounts to explaining the semantics of -> let. It's fine if that's a TODO, I just want to make sure it doesn't get lost.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how this would remove the explanation of the semantics of -> val Foo?

I also think we don't yet know the exact model we want here in terms of value representation, and so not sure there is anything to really do here yet.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how this would remove the explanation of the semantics of -> val Foo?

Sorry, I was unclear. It seems like that section's explanation of the alternate semantics that the compiler is allowed to give to -> Foo, is also an explanation of the semantics of -> val Foo. If so, that material should either be replaced with a cross-reference to the canonical documentation for -> val Foo, or it should be relocated and rephrased in order to become the canonical documentation for -> val Foo (leaving behind a cross-reference to the new location).

I also think we don't yet know the exact model we want here in terms of value representation, and so not sure there is anything to really do here yet.

You think it's too soon to even have a TODO?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a TODO.


Expand Down Expand Up @@ -555,6 +555,12 @@ functions with a `()` return type for the purpose of expression categories.

#### Deferred initialization from values and references

TODO: This section needs to be updated to reflect the addition of `-> val`
returns in [proposal #5434](/proposals/p5434.md). This section could be replaced
by a statement that initializing returns may be replaced by value returns when
that is safe and correct, moving much of this content into a description of how
value returns works.

Carbon also makes the evaluation of function calls and return statements tightly
linked in order to enable more efficiency improvements. It allows the actual
initialization performed by the `return` statement with its expression to be
Expand Down Expand Up @@ -640,6 +646,9 @@ specialized constructs given the specialized nature of these operations.

### Reference types

TODO: This section needs to be updated to reflect
[proposal #5434](/proposals/p5434.md).

Unlike C++, Carbon does not currently have reference types. The only form of
indirect access are pointers. There are a few aspects to this decision that need
to be separated carefully from each other as the motivations and considerations
Expand Down Expand Up @@ -883,12 +892,12 @@ keyword. It isn't final at all and likely will need to change to read well.
The provided representation type must be one of the following:

- `const Self` -- this forces the use of a _copy_ of the object.
- `const Self *` -- this forces the use of a [_pointer_](#pointers) to the
original object.
- `const ref` -- this forces the use of a [_pointer_](#pointers) to the
original object, but with the `const` API subset.
- A custom type that is not `Self`, `const Self`, or a pointer to either.

If the representation is `const Self` or `const Self *`, then the type fields
will be accessible as [_value expressions_](#value-expressions) using the normal
If the representation is `const Self` or `const ref`, then the type fields will
be accessible as [_value expressions_](#value-expressions) using the normal
member access syntax for value expressions of a type. These will be implemented
by either accessing a copy of the object in the non-pointer case or a pointer to
the original object in the pointer case. A representation of `const Self`
Expand All @@ -899,7 +908,7 @@ used.
If no customization is provided, the implementation will select one based on a
set of heuristics. Some examples:

- Non-copyable types and polymorphic types would use a `const Self*`.
- Non-copyable types and polymorphic types would use a `const ref`.
- Small objects that are trivially copied in a machine register would use
`const Self`.

Expand Down
Loading
Loading