Skip to content

Commit 9a922ad

Browse files
committed
Address feedback, delegating expand api work to a future proposal
1 parent c5168c9 commit 9a922ad

File tree

1 file changed

+49
-35
lines changed

1 file changed

+49
-35
lines changed

proposals/p3720.md

Lines changed: 49 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3030
- [Binding to the members of another type](#binding-to-the-members-of-another-type)
3131
- [Other uses of `extend api`](#other-uses-of-extend-api)
3232
- [C++ operator overloading](#c-operator-overloading)
33+
- [Future work](#future-work)
3334
- [Future: tuple indexing](#future-tuple-indexing)
3435
- [Future: properties](#future-properties)
36+
- [Future: building block for language features such as API extension](#future-building-block-for-language-features-such-as-api-extension)
3537
- [Rationale](#rationale)
3638
- [Alternatives considered](#alternatives-considered)
3739
- [Swap the bind interface parameters](#swap-the-bind-interface-parameters)
@@ -140,6 +142,9 @@ interface TypeBind(T:! type) {
140142
}
141143
```
142144

145+
> **Note:** `TypeBind` is its own binding interface since the members of a type
146+
> are defined by their values, not by their type.
147+
143148
The other member access operators -- `x.y`, `x->y`, and `x->(y)` -- are defined
144149
by how they rewrite into the `x.(y)` form using these two rules:
145150

@@ -278,36 +283,14 @@ How does this arise?
278283
>
279284
> Note that if `M` is an overloaded name, it could be an instance member in some
280285
> cases and a non-instance member in others, depending on the arguments passed.
281-
> This is another reason to delegate this to linters on a best-effort error
282-
> basis analyzing a whole expression, rather than a strict rule just about
286+
> This is another reason to delegate this to linters analyzing a whole
287+
> expression on a best-effort basis, rather than a strict rule just about
283288
> binding.
284289
285-
The binding operators are defined using three dedicated interfaces:
286-
287-
```carbon
288-
// For value `x` with type `T` and `y` of type `U`,
289-
// `x.(y)` is `y.((U as ValueBind(T)).Op)(x)`
290-
interface ValueBind(T:! type) {
291-
let Result:! type;
292-
fn Op[self: Self](x: T) -> Result;
293-
}
294-
295-
// For reference expression `var x: T` and `y` of type `U`,
296-
// `x.(y)` is `*y.((U as RefBind(T)).Op)(&x)`
297-
interface RefBind(T:! type) {
298-
let Result:! type;
299-
fn Op[self: Self](p: T*) -> Result*;
300-
}
301-
302-
// For a facet value `T`, `y` of type `U`,
303-
// `T.(y)` is `y.((U as TypeBind(T)).Op)()`.
304-
interface TypeBind(T:! type) {
305-
let Result:! type;
306-
fn Op[self: Self]() -> Result;
307-
}
308-
```
309-
310-
These binding operations are implemented for the types of the class members:
290+
The binding operators are defined using three dedicated interfaces --
291+
`ValueBind`, `RefBind`, and `TypeBind` --
292+
[as defined in the "proposal" section](#proposal). These binding operations are
293+
implemented for the types of the class members:
311294
312295
```carbon
313296
impl __TypeOf_C_F as ValueBind(C)
@@ -875,12 +858,18 @@ class Box(T:! type) {
875858
```
876859
877860
This means that lookup into `Box(T)` also looks in the type `T` for members. In
878-
this way, `b.Search` will find `b.(String.Search)`. The general rule for
879-
`extend`, which we apply here as well, is that if lookup into `Box(T)` succeeds,
880-
then that result is used and no lookup into `T` is performed. The extended type
881-
must be complete. If a class uses `extend` more than once, and finds the same
882-
name more than once, that is an ambiguity error that needs to be resolved by
883-
qualifying the name on use.
861+
this way, `b.Search` will find `b.(String.Search)`. The extended type is
862+
required to be complete at the point of the `extend api` declaration, so these
863+
lookups into `T` can succeed.
864+
865+
The general rule for resolving ambiguity for `extend`, which we apply here as
866+
well, is that if lookup into `Box(T)` succeeds, then that result is used and no
867+
lookup into `T` is performed. If a class uses `extend` more than once, and finds
868+
the same name more than once, that is an ambiguity error that needs to be
869+
resolved by qualifying the name on use.
870+
871+
> **TODO:** Are these the right rules in the context of API evolution? See
872+
> [comment on #3720](https://github.com/carbon-language/carbon-lang/pull/3720/files#r1527084183).
884873
885874
> **Note:** This is an alternative to defining an `alias` for each member of the
886875
> extended type. This avoids having to repeat them, which is both lengthy and
@@ -892,7 +881,12 @@ Like other uses of `extend`, an `extend api` declaration do not have access
892881
control modifiers and only operate on public names.
893882

894883
> **Future:** We might want `extend api` to also get (some) interface
895-
> implementations, like `extend base` does.
884+
> implementations, like `extend base` does. Or this may be provided by a
885+
> different mechanism, for example that allows customization of impl binding by
886+
> implementing an interface. See
887+
> [this comment on #3720](https://github.com/carbon-language/carbon-lang/pull/3720/files#r1527083149)
888+
> and
889+
> [2024-03-18 open discussion](https://docs.google.com/document/d/1s3mMCupmuSpWOFJGnvjoElcBIe2aoaysTIdyczvKX84/edit?resourcekey=0-G095Wc3sR6pW1hLJbGgE0g&tab=t.0#heading=h.23p8d6pqg1qp).
896890
897891
#### Binding to the members of another type
898892

@@ -941,6 +935,18 @@ With these two ingredients, `b.Search(32)` is equivalent to
941935

942936
### Other uses of `extend api`
943937

938+
> TODO: Give the example of reference library type from
939+
> [this comment on #3720](https://github.com/carbon-language/carbon-lang/pull/3720/files#r1513712572).
940+
941+
> TODO: Show how to model other language constructs with `extend api`, custom
942+
> binding, and implicit (or explicit) conversions, as described in
943+
> [this comment on #3720](https://github.com/carbon-language/carbon-lang/pull/3720/files#r1527089564):
944+
>
945+
> - other uses of `extend`,
946+
> - inheritance,
947+
> - virtual dispatch, and
948+
> - mixins.
949+
944950
The [`extend api` mechanism](#extend-api), allowing lookup to find names from
945951
another type, has other uses beyond [member forwarding](#member-forwarding).
946952

@@ -1058,6 +1064,8 @@ just for C++ interop that invokes the C++ arrow operator, such as
10581064
and in
10591065
[a comment on this proposal](https://github.com/carbon-language/carbon-lang/pull/3720/files#r1507917882).
10601066

1067+
## Future work
1068+
10611069
### Future: tuple indexing
10621070

10631071
We can reframe the use of the compound member access syntax for tuple fields as
@@ -1098,6 +1106,12 @@ interfaces. The compiler would try them in a specified order and use the one it
10981106
found first. This has the downside of the possibility of different behavior in a
10991107
checked generic context where only some of the implementations are visible.
11001108

1109+
### Future: building block for language features such as API extension
1110+
1111+
We should be able to express other language features, such as API extension, in
1112+
terms of customized binding, plus possibly some new language primitives. This
1113+
should be explored in a future proposal.
1114+
11011115
## Rationale
11021116

11031117
This proposal is about:

0 commit comments

Comments
 (0)