StoredPropertyIterable

Having a way to get a collection of key paths for a type makes a lot of sense. I think it makes sense not to make this about stored properties per se, but about the set of properties that make up the logical "schema" of the type; the set of stored properties makes sense as the default schema for a struct, but it would be useful to be able to override that default with a set of computed properties or subscripts that cover the type.

For collections, there's also the issue that the schema is value-dependent rather than uniform for all instances of a type, so you might want to have separate static and instance properties in the protocol to model this:

protocol KeyPathSchema {
  static var typeSchema: [PartialKeyPath<Self>]
  var valueSchema: [PartialKeyPath<Self>]
}

let x = [1, 2, 3]
type(of: x).typeSchema // []
x.valueSchema // [\.[0], \.[1], \.[2]]

I could see this all being particularly useful with compile-time evaluation, since you could use the statically-known layout of types to generate per-field logic based on those layouts. However, with the limited closed hierarchy of key paths that exist now, it isn't ideal to use key paths as a seed for generating things like Hashable conformance, since there's no way to state the requirement that all the fields in a schema must themselves be Hashable for the default implementation to be viable. Eventually, if we had "protocol-oriented" keypaths and generalized existentials, it'd be nice to be able to express this as conditional constraints on the key path collection:

protocol KeyPathSchema {
  associatedtype Schema: Collection where Schema.Element: KeyPath
}

extension Hashable where Self: KeyPathSchema, Self.Schema.Element.Value: Hashable {
  ...
}
10 Likes