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

Generic details 12: parameterized types #1146

Merged
merged 14 commits into from
Apr 28, 2022
34 changes: 31 additions & 3 deletions docs/design/generics/details.md
Original file line number Diff line number Diff line change
Expand Up @@ -4917,9 +4917,37 @@ class Optional(T:! Movable) {
Note that the constraint on `T` is just `Movable`, not
`Movable & OptionalStorage`, since the `Movable` requirement is
[sufficient to guarantee](#lookup-resolution-and-specialization) that some
implementation of `OptionalStorage` exists for `T`. Adding `OptionalStorage` to
the constraints on `T` would make `Optional` harder for clients and obscure what
types can be used with `Optional`.
implementation of `OptionalStorage` exists for `T`. Carbon does not require that
callers of `Optional`, even generic callers, to specify that the argument type
implements `OptionalStorage`:
josh11b marked this conversation as resolved.
Show resolved Hide resolved

```
// ✅ Allowed: `T` just needs to be `Movable` to form
// `Optional(T)`, not `OptionalStorage`.
josh11b marked this conversation as resolved.
Show resolved Hide resolved
fn First[T:! Movable & Eq](v: Vector(T)) -> Optional(T);
```

Adding `OptionalStorage` to the constraints on the parameter to `Optional` would
obscure what types can be used as arguments. `OptionalStorage` is an
implementation detail of `Optional` and need not appear in its public API.

In this example, a `let` is used to avoid repeating `OptionalStorage` in the
definition of `Optional`, since it has no name conflicts with the members of
`Movable`:

```
class Optional(T:! Movable) {
private let U:! Movable & OptionalStorage = T;
fn None() -> Self {
return {.storage = U.MakeNone()};
}
fn Some(x: T) -> Self {
return {.storage = u.Make(x)};
}
...
private var storage: U.Storage;
}
```

## Future work

Expand Down
4 changes: 2 additions & 2 deletions executable_semantics/syntax/parser.ypp
Original file line number Diff line number Diff line change
Expand Up @@ -903,9 +903,9 @@ declaration:
}
| INTERFACE identifier LEFT_CURLY_BRACE declaration_list RIGHT_CURLY_BRACE
{
auto ty_ty = arena->New<TypeTypeLiteral>(context.source_loc());
auto ty_ty = arena -> New<TypeTypeLiteral>(context.source_loc());
auto self =
arena->New<GenericBinding>(context.source_loc(), "Self", ty_ty);
arena -> New<GenericBinding>(context.source_loc(), "Self", ty_ty);
josh11b marked this conversation as resolved.
Show resolved Hide resolved
$$ = arena->New<InterfaceDeclaration>(context.source_loc(), $2, self, $4);
}
| impl_kind IMPL expression AS expression LEFT_CURLY_BRACE declaration_list RIGHT_CURLY_BRACE
Expand Down