Consider the following two protocols:
protocol Parser {
associatedtype ResultType
func parse(_ data: Data) throws -> ResultType
}
protocol JSONParser: Parser {
func parse(_ json: [AnyHashable:Any]) throws -> ResultType
}
extension JSONParser {
func parse(_ data: Data) throws -> ResultType {
return try parse([:])
}
}
Basically we have a base "raw" parser that parse data, and an "enhanced" child protocol that decodes the data into a dictionary and allows conforming types to access the decoded JSON.
Now, the problem is with the type witness inference that no longer works for types adopting the child protocol.
This works:
class RawNumberParser: Parser {
func parse(_ data: Data) throws -> Int {
return data.count
}
}
, as the compiler automatically infer the type Int
for the ResultType
associated type.
However, the following code doesn't compile:
class AdvancedNumberParser: JSONParser {
func parse(_ json: [AnyHashable : Any]) throws -> Int {
return json.count
}
}
error: type 'AdvancedNumberParser' does not conform to protocol 'JSONParser'
Explicitly declaring the type alias makes the error go away:
class AdvancedNumberParser: JSONParser {
typealias ResultType = Int
func parse(_ json: [AnyHashable : Any]) throws -> Int {
return json.count
}
}
Am I missing some declarations, or is the compiler not capable to infer the associated type for the child protocol?
Found a workaround: adding an associated type in the child protocol:
protocol JSONParser: Parser {
associatedtype JSONResultType = ResultType
func parse(_ json: [AnyHashable:Any]) throws -> JSONResultType
}
extension JSONParser {
func parse(_ data: Data) throws -> JSONResultType {
return try parse([:])
}
}
For some reason it seems the type witness inference is shallow, it maps only for the current level.