On the example of AttributedString type it is not very clear how the dynamicMemberLookup chaining works from
@dynamicMemberLookup
struct AttributedString {
subscript<K>(dynamicMember keyPath: Swift.KeyPath<AttributeDynamicLookup, K>) -> K.Value? where K: AttributedStringKey {
// ...
}
}
through
public extension AttributeDynamicLookup {
subscript<T: AttributedStringKey>(dynamicMember keyPath: KeyPath<AttributeScopes.FoundationAttributes, T>) -> T {
// ... <--- Not called!!!
}
}
What's not clear here is that the second subscript is not called at all. How does it work?
var attr = AttributedString()
_ = attr.foo
// ...
extension AttributeDynamicLookup {
subscript<T>(dynamicMember keyPath: KeyPath<AttributeScopes.MyAttributes, T>) -> T where T: AttributedStringKey {
self[T.self] // <--- Not called!!!
}
}
extension AttributeScopes {
var my: AttributeScope.Type {
MyAttributes.self
}
struct MyAttributes: AttributeScope {
let foo: FooAttribute
}
}
enum FooAttribute: AttributedStringKey {
typealias Value = Int
static let name = "MyAttribute"
}
// ...
@dynamicMemberLookup
struct AttributedString {
subscript<K>(dynamicMember keyPath: Swift.KeyPath<AttributeDynamicLookup, K>) -> K.Value? where K: AttributedStringKey {
self[K.self]
}
subscript<K>(_: K.Type) -> K.Value? where K: AttributedStringKey {
// ...
}
}
@dynamicMemberLookup
enum AttributeDynamicLookup {
subscript<T>(_: T.Type) -> T where T: AttributedStringKey {
fatalError()
}
}
public enum AttributeScopes {
}
protocol AttributeScope {
}
public protocol AttributedStringKey {
associatedtype Value: Hashable
static var name: String { get }
}