Reputation: 369
It seems absurd that this method signature does not compile in Swift 4:
class Bar<ValueType> {
func version() throws -> String where ValueType == [String: Any] { ... }
}
(Error: where clause cannot be attached to a non-generic declaration)
but this compiles fine:
class Bar<ValueType> {
func version<T>(_ foo: T? = nil) throws -> String where ValueType == [String: Any] { ... }
}
Anyone have insight as to why this is the case?
Upvotes: 5
Views: 5210
Reputation: 181
That has been finally allowed in Swift 5.3. See Contextual Where Clauses in the official Language Guide.
Citing from there:
You can write a generic
where
clause as part of a declaration that doesn’t have its own generic type constraints, when you’re already working in the context of generic types. For example, you can write a genericwhere
clause on a subscript of a generic type or on a method in an extension to a generic type....
extension Container { func average() -> Double where Item == Int { var sum = 0.0 for index in 0..<count { sum += Double(self[index]) } return sum / Double(count) }
That compiles just fine in Xcode 12 beta 4, but won't work in Xcode 11.6 that is shipped with Swift 5.2.4.
Upvotes: 2
Reputation: 63271
Because ValueType
has nothing to do with this method (in the first example). It would be wrong to put such a method in a type (class
/struct
/enum
), since it's not really a true member of that type. It's conditionally a member of that type, depending on the truth value of the where
clause.
To achieve this, you would want to put this method in an extension of your type, with the where
clause you want. E.g.
extension YourType where ValueType == [String: Any] {
func version() throws -> String { ... }
}
Upvotes: 3