I am trying to make an extension to a generic class which is constrained by the type of the generic. This is a simplification of the code I believe should work:
struct Thing<T> {
var value: T
}
struct ContainsStringThing {
var stringThing: Thing<String>
}
extension Thing where T == String { // <-- Error location
func containedStringThing() -> ContainsStringThing {
return ContainsStringThing(stringThing: value)
}
}
However, I get the following error message:
Same-type requirement makes generic Parameter 'T' non-generic
I searched for a way to fix this and found a suggestion to use a protocol to constrain the extension instead of a type: link to article. After doing that I ended up with this:
protocol StringProtocol { }
struct Thing<T> {
var value: T
}
struct ContainsStringThing {
var stringThing: Thing<StringProtocol>
}
extension Thing where T: StringProtocol {
func containedStringThing() -> ContainsStringThing {
return ContainsStringThing(stringThing: self) // <-- Error location
}
}
Now it does let me constrain the extension but it shows a different error message:
Cannot convert value of type 'Thing<T>' to expected argument type 'Thing<StringProtocol>'
Basically now it knows that T
conforms to protocol StringProtocol
by itself, but it doesn't know it when referring to the whole object Thing<T>
.
is there any workaround to this or should I submit it as an evolution proposal to the swift mailing list?
Note: All the code is tested on a playground, you can just copy and paste it to try it.