mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 19:40:10 +01:00
Explain more on the difference of where constraints (#4551)
This adds language to explain where the types of constraints can or can not appear (attached-to an impl-as vs in-a type expression). And describes the impact of using a rewrite vs same-type constraint inside the body of the affected code, and thus why a rewrite is preferable when the constraint is of a single facet type.
This commit is contained in:
@@ -2326,7 +2326,7 @@ fn PeekAtTopOfStackParameterizedImpl
|
||||
...
|
||||
}
|
||||
fn PeekAtTopOfStackParameterized[StackType:! type]
|
||||
(s: StackType*, T:! type where StackType is StackParameterized(T)) -> T {
|
||||
(s: StackType*, T:! type where StackType impls StackParameterized(T)) -> T {
|
||||
return PeekAtTopOfStackParameterizedImpl(T, StackType, s);
|
||||
}
|
||||
|
||||
@@ -2505,8 +2505,21 @@ binary operator:
|
||||
- _Same-type constraints_: `where`...`==`...
|
||||
- _Implements constraints_: `where`...`impls`...
|
||||
|
||||
And there are two positions that `where` can be written:
|
||||
|
||||
- At the end of an `impl as` declaration, before the body of the impl.
|
||||
```carbon
|
||||
impl Class as Interface where .A = i32 { ... }
|
||||
```
|
||||
- Inside a type expression.
|
||||
```carbon
|
||||
fn F[T: Interface where .A impls OtherInterface](t: T) { ... }
|
||||
```
|
||||
|
||||
A rewrite constraint is written `where .A = B`, where `A` is the name of an
|
||||
[associated constant](#associated-constants) which is rewritten to `B`.
|
||||
[associated constant](#associated-constants) which is rewritten to `B`. Any use
|
||||
of `.A` thereafter is the same as using `B`, including direct access to the API
|
||||
of `B`.
|
||||
|
||||
The "dot followed by the name of a member" construct, like `.A`, is called a
|
||||
_designator_. The name of the designator is looked up in the constraint, and
|
||||
@@ -2518,15 +2531,20 @@ constraint.
|
||||
> constraint is satisfied.
|
||||
|
||||
A same-type constraint is written `where X == Y`, where `X` and `Y` both name
|
||||
facets. The constraint is that `X as type` must be the same as `Y as type`. In
|
||||
cases where a constraint may be written in either form, prefer a rewrite
|
||||
constraint over a same-type constraint. Note that switching between the two
|
||||
forms does not change which types satisfies the constraint, and so is a
|
||||
compatible change for callers.
|
||||
facets. The constraint is that `X as type` must be the same as `Y as type`. It
|
||||
would normally only be used in the type expression position.
|
||||
|
||||
A same-type constraint does not rewrite the type on the left-hand side to the
|
||||
right-hand side, and they are still treated as distinct types. A value of type
|
||||
`X` [would need to be cast](#satisfying-both-facet-types) to `Y` in order to use
|
||||
the API of `Y`. So for constraint clauses that name a single facet type on the
|
||||
right-hand side, using a rewrite constraint is preferred. Note that switching
|
||||
between the two forms does not change which types satisfies the constraint, and
|
||||
so is a compatible change for callers.
|
||||
|
||||
An implements constraint is written `where T impls C`, where `T` is a facet and
|
||||
`C` is a facet type. The constraint is that `T` satisfies the requirements of
|
||||
`C`.
|
||||
`C`. It would normally only be used in the type expression position.
|
||||
|
||||
**References:** The definition of rewrite and same-type constraints were in
|
||||
[proposal #2173](https://github.com/carbon-language/carbon-lang/pull/2173).
|
||||
@@ -2600,7 +2618,7 @@ interface Container {
|
||||
let IteratorType:! Iterator where .ElementType = ElementType;
|
||||
|
||||
// `.Self` means `SliceType`.
|
||||
let SliceType:! Container where .Self is SliceConstraint(ElementType, .Self);
|
||||
let SliceType:! Container where .Self impls SliceConstraint(ElementType, .Self);
|
||||
|
||||
// `Self` means the type implementing `Container`.
|
||||
fn GetSlice[addr self: Self*]
|
||||
@@ -2989,7 +3007,7 @@ notionally does much the same thing as
|
||||
impl A as SameAs(C) { ... }
|
||||
```
|
||||
|
||||
where the `impl` makes use of `A is SameAs(B)` and `B is SameAs(C)`.
|
||||
where the `impl` makes use of `A impls SameAs(B)` and `B impls SameAs(C)`.
|
||||
|
||||
In general, an `observe` declaration lists a sequence of
|
||||
[type expressions](terminology.md#type-expression) that are equal by some
|
||||
|
||||
Reference in New Issue
Block a user