@@ -112,6 +112,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
112
112
- [ Bridge for C++ customization points] ( #bridge-for-c-customization-points )
113
113
- [ Variadic arguments] ( #variadic-arguments )
114
114
- [ Range constraints on generic integers] ( #range-constraints-on-generic-integers )
115
+ - [ Separate declaration and definition of impl] ( #separate-declaration-and-definition-of-impl )
115
116
- [ References] ( #references )
116
117
117
118
<!-- tocstop -->
@@ -1900,30 +1901,38 @@ interface NSpacePoint {
1900
1901
}
1901
1902
```
1902
1903
1903
- Implementations of `NSpacePoint` for different types might have different values
1904
- for `N`:
1904
+ An implementation of an interface specifies values for associated constants with
1905
+ a [`where` clause](#where-constraints). For example, implementations of
1906
+ `NSpacePoint` for different types might have different values for `N`:
1905
1907
1906
1908
```
1907
1909
class Point2D {
1908
- impl as NSpacePoint {
1909
- let N:! i32 = 2;
1910
+ impl as NSpacePoint where .N = 2 {
1910
1911
fn Get[ addr me: Self* ] (i: i32) -> f64 { ... }
1911
1912
fn Set[ addr me: Self* ] (i: i32, value: f64) { ... }
1912
1913
fn SetAll[ addr me: Self* ] (value: Array(f64, 2)) { ... }
1913
1914
}
1914
1915
}
1915
1916
1916
1917
class Point3D {
1917
- impl as NSpacePoint {
1918
- let N:! i32 = 3;
1918
+ impl as NSpacePoint where .N = 3 {
1919
1919
fn Get[ addr me: Self* ] (i: i32) -> f64 { ... }
1920
1920
fn Set[ addr me: Self* ] (i: i32, value: f64) { ... }
1921
1921
fn SetAll[ addr me: Self* ] (value: Array(f64, 3)) { ... }
1922
1922
}
1923
1923
}
1924
1924
```
1925
1925
1926
- And these values may be accessed as members of the type:
1926
+ Multiple assignments to associated constants may be joined using the `and`
1927
+ keyword. The list of assignments is subject to two restrictions:
1928
+
1929
+ - An implementation of an interface cannot specify a value for a
1930
+ [`final`](#final-members) associated constant.
1931
+ - If an associated constant doesn't have a
1932
+ [default value](#interface-defaults), every implementation must specify its
1933
+ value.
1934
+
1935
+ These values may be accessed as members of the type:
1927
1936
1928
1937
```
1929
1938
Assert(Point2D.N == 2);
@@ -2021,9 +2030,8 @@ class DynamicArray(T:! Type) {
2021
2030
fn Insert[ addr me: Self* ] (pos: IteratorType, value: T);
2022
2031
fn Remove[ addr me: Self* ] (pos: IteratorType);
2023
2032
2024
- impl as StackAssociatedType {
2025
- // Set the associated type ` ElementType ` to ` T ` .
2026
- let ElementType:! Type = T;
2033
+ // Set the associated type ` ElementType ` to ` T ` .
2034
+ impl as StackAssociatedType where .ElementType = T {
2027
2035
fn Push[ addr me: Self* ] (value: ElementType) {
2028
2036
me->Insert(me->End(), value);
2029
2037
}
@@ -2442,6 +2450,10 @@ constraint Point2DInterface {
2442
2450
}
2443
2451
```
2444
2452
2453
+ This syntax is also used to specify the values of
2454
+ [associated constants](#associated-constants) when implementing an interface for
2455
+ a type.
2456
+
2445
2457
**Concern:** Using `=` for this use case is not consistent with other `where`
2446
2458
clauses that write a boolean expression that evaluates to `true` when the
2447
2459
constraint is satisfied.
@@ -2486,6 +2498,9 @@ constraint IntStack {
2486
2498
}
2487
2499
```
2488
2500
2501
+ This syntax is also used to specify the values of
2502
+ [associated types](#associated-types) when implementing an interface for a type.
2503
+
2489
2504
##### Equal generic types
2490
2505
2491
2506
Alternatively, two generic types could be constrained to be equal to each other,
@@ -3534,8 +3549,7 @@ lexically in the class' scope:
3534
3549
3535
3550
```
3536
3551
class Vector(T:! Type) {
3537
- impl as Iterable {
3538
- let ElementType:! Type = T;
3552
+ impl as Iterable where .ElementType = T {
3539
3553
...
3540
3554
}
3541
3555
}
@@ -3545,8 +3559,7 @@ This is equivalent to naming the type between `impl` and `as`:
3545
3559
3546
3560
```
3547
3561
class Vector(T:! Type) {
3548
- impl Vector(T) as Iterable {
3549
- let ElementType:! Type = T;
3562
+ impl Vector(T) as Iterable where .ElementType = T {
3550
3563
...
3551
3564
}
3552
3565
}
@@ -3556,13 +3569,13 @@ An impl may be declared [external](#external-impl) by adding an `external`
3556
3569
keyword before `impl`. External impls may also be declared out-of-line:
3557
3570
3558
3571
```
3559
- external impl [ T:! Type] Vector(T) as Iterable {
3560
- let ElementType:! Type = T;
3572
+ external impl [ T:! Type] Vector(T) as Iterable
3573
+ where .ElementType = T {
3561
3574
...
3562
3575
}
3563
3576
// This syntax is also allowed:
3564
- external impl Vector(T:! Type) as Iterable {
3565
- let ElementType:! Type = T;
3577
+ external impl Vector(T:! Type) as Iterable
3578
+ where .ElementType = T {
3566
3579
...
3567
3580
}
3568
3581
```
@@ -3758,9 +3771,8 @@ where blanket impls arise:
3758
3771
- `T` implements `CommonType(T)` for all `T`
3759
3772
3760
3773
```
3761
- external impl [T:! Type] T as CommonType(T) {
3762
- let Result:! auto = T;
3763
- }
3774
+ external impl [T:! Type] T as CommonType(T)
3775
+ where .Result = T { }
3764
3776
```
3765
3777
3766
3778
This means that every type is the common type with itself.
@@ -3857,6 +3869,8 @@ parameters are replaced the declarations are normalized as follows:
3857
3869
between the `impl` and `as` keywords if the type is left out.
3858
3870
- Pointer types `T*` are replaced with `Ptr(T)`.
3859
3871
- The `external` keyword is removed, if present.
3872
+ - Any `where` clauses that are setting associated constants or types are
3873
+ removed.
3860
3874
3861
3875
The type structure will always contain a single interface name, which is the
3862
3876
name of the interface being implemented, and some number of type names. Type
@@ -3995,12 +4009,10 @@ interface True {}
3995
4009
impl Y as True {}
3996
4010
interface Z(T:! Type) { let Cond:! Type; }
3997
4011
match_first {
3998
- impl [ T:! Type, U:! Z(T) where .Cond is True] T as Z(U) {
3999
- let Cond:! Type = N;
4000
- }
4001
- impl [ T:! Type, U:! Type] T as Z(U) {
4002
- let Cond:! Type = Y;
4003
- }
4012
+ impl [ T:! Type, U:! Z(T) where .Cond is True] T as Z(U)
4013
+ where .Cond = N { }
4014
+ impl [ T:! Type, U:! Type] T as Z(U)
4015
+ where .Cond = Y { }
4004
4016
}
4005
4017
```
4006
4018
@@ -4026,15 +4038,12 @@ class B {}
4026
4038
class C {}
4027
4039
interface D(T:! Type) { let Cond:! Type; }
4028
4040
match_first {
4029
- impl [ T:! Type, U:! D(T) where .Cond = B] T as D(U) {
4030
- let Cond:! Type = C;
4031
- }
4032
- impl [ T:! Type, U:! D(T) where .Cond = A] T as D(U) {
4033
- let Cond:! Type = B;
4034
- }
4035
- impl [ T:! Type, U:! Type] T as D(U) {
4036
- let Cond:! Type = A;
4037
- }
4041
+ impl [ T:! Type, U:! D(T) where .Cond = B] T as D(U)
4042
+ where .Cond = C { }
4043
+ impl [ T:! Type, U:! D(T) where .Cond = A] T as D(U)
4044
+ where .Cond = B { }
4045
+ impl [ T:! Type, U:! Type] T as D(U)
4046
+ where .Cond = A { }
4038
4047
}
4039
4048
```
4040
4049
@@ -4121,15 +4130,13 @@ interface Deref {
4121
4130
// Types implementing ` Deref `
4122
4131
class Ptr(T:! Type) {
4123
4132
...
4124
- external impl as Deref {
4125
- let Result:! Type = T;
4133
+ external impl as Deref where .Result = T {
4126
4134
fn DoDeref[ me: Self] ( ) -> Result { ... }
4127
4135
}
4128
4136
}
4129
4137
class Optional(T:! Type) {
4130
4138
...
4131
- external impl as Deref {
4132
- let Result:! Type = T;
4139
+ external impl as Deref where .Result = T {
4133
4140
fn DoDeref[ me: Self] ( ) -> Result { ... }
4134
4141
}
4135
4142
}
@@ -4159,16 +4166,14 @@ To mark an impl as not able to be specialized, prefix it with the keyword
4159
4166
class Ptr(T:! Type) {
4160
4167
...
4161
4168
// Note: added ` final `
4162
- final external impl as Deref {
4163
- let Result:! Type = T;
4169
+ final external impl as Deref where .Result = T {
4164
4170
fn DoDeref[ me: Self] ( ) -> Result { ... }
4165
4171
}
4166
4172
}
4167
4173
class Optional(T:! Type) {
4168
4174
...
4169
4175
// Note: added ` final `
4170
- final external impl as Deref {
4171
- let Result:! Type = T;
4176
+ final external impl as Deref where .Result = T {
4172
4177
fn DoDeref[ me: Self] ( ) -> Result { ... }
4173
4178
}
4174
4179
}
@@ -4539,6 +4544,14 @@ between multiple generic integer parameters. For example, if `J < K` and
4539
4544
secondary syntactic concern about how to write this kind of constraint on a
4540
4545
parameter, as opposed to an associated type, as in `N:! u32 where ___ >= 2`.
4541
4546
4547
+ ### Separate declaration and definition of impl
4548
+
4549
+ There is a desire to support a short declaration that a type implements an
4550
+ interface without giving a full definition of that implementation for API files.
4551
+ Everything needed for type checking is provided in the interface definition,
4552
+ except for the assignments to associated constants and types, and so those must
4553
+ be included in the declaration as well.
4554
+
4542
4555
## References
4543
4556
4544
4557
- [#553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553)
@@ -4549,3 +4562,4 @@ parameter, as opposed to an associated type, as in `N:! u32 where ___ >= 2`.
4549
4562
- [#950: Generic details 6: remove facets](https://github.com/carbon-language/carbon-lang/pull/950)
4550
4563
- [#983: Generic details 7: final impls](https://github.com/carbon-language/carbon-lang/pull/983)
4551
4564
- [#990: Generics details 8: interface default and final members](https://github.com/carbon-language/carbon-lang/pull/990)
4565
+ - [#1013: Generics: Set associated constants using where constraints](https://github.com/carbon-language/carbon-lang/pull/1013)
0 commit comments