Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Generic parameterized impls (details 5) (#920)
There are cases where an impl definition should apply to more than a single type and interface combination. The solution is to parameterize the impl definition, so it applies to a family of types, interfaces, or both. This includes: - Declare an impl for a parameterized type, which may be external or declared out-of-line. ``` external impl [T:! Type] Vector(T) as Iterable { ... } external impl Vector(T:! Type) as Iterable { ... } ``` - "Conditional conformance" where a parameterized type implements some interface if the parameter to the type satisfies some criteria, like implementing the same interface. ``` external impl [T:! Type] Pair(T, T) as Foo(T) { ... } class Array(T:! Type, template N:! Int) { impl [P:! Printable] Array(P, N) as Printable { ... } impl Array(P:! Printable, N) as Printable { ... } } ``` - "Blanket" impls where an interface is implemented for all types that implement another interface, or some other criteria beyond being a specific type. ``` external impl [T:! Ordered] T as PartiallyOrdered { ... } ``` - "Wildcard" impls where a family of interfaces are implemented for single type. ``` class BigInt { external impl [T:! ImplicitAs(i32)] as AddTo(T) { ... } external impl as AddTo(T:! ImplicitAs(i32)) { ... } } external impl [T:! ImplicitAs(i32)] BigInt as AddTo(T) { ... } external impl BigInt as AddTo(T:! ImplicitAs(i32)) { ... } ``` In addition to a syntax for defining parameterized impls, we need rules for coherence: - Orphan rules that ensure that impls are imported in any code that might use it. - We need overlap rules that pick a specific impl when more than one impl declaration matches a specific query about whether a type implements an interface. Co-authored-by: Richard Smith <richard@metafoo.co.uk>
- Loading branch information