I'm trying to create a generic type that has a mix of dynamic and computed properties depending on the type parameter.
I'm trying to do this with dynamic member lookup and generic type constraints, but I'm running into a compiler error.
@dynamicMemberLookup
struct Container<T> {
subscript(dynamicMember member: String) -> String {
return "dynamic"
}
}
extension Container where T: StringProtocol {
var name: String { return "computed" }
}
let one = Container<String>()
// Prints "computed" as expected.
print(one.name)
let two = Container<Int>()
// Compiler error: Type 'Int' does not conform to protocol 'StringProtocol'.
// I expected it to compile and print "dynamic".
print(two.name)
I've also tried isolating the dynamic member lookup conformance to its own extension with different type constraints, but that didn't help. I've tried using same type constraints instead of a protocol where clause, but still no luck.
My understanding is that dynamic member lookup only kicks in if an overload set is empty, but in your case, the 'name' property is going to be there (even though it has conditional requirements on it; those are checked after name lookup has been performed). I'm guessing this will be difficult to change.
Sorry for not noticing this when it went by. Slava is right: by design, DML only kicks in when there are no overloads visible. If you have visible overloads that are not viable (e.g. because of failed constraints, access control, etc ... ) then DML won't kick in. I am not sure if this should be considered a bug or a feature, and am not sure whether a full proposal is required. I'd suggest starting a thread on swift-evolution to see what others think.