I don't understand why generics need to be type-erased using wrapper types. It seems like extra boilerplate to write, when the following should work (at least intuitively).
struct GenericContainer<X> {
let x: X
}
protocol AnyContainer {
var x: Any { get }
}
extension GenericContainer: AnyContainer {}
// error: type 'GenericContainer<X>' does not conform to protocol 'AnyContainer'
// note: candidate has non-matching type 'X'
// note: protocol requires property 'x' with type 'Any'; do you want to add a stub?
Why doesn't it work? "X" downcasts to "Any." E.g.
...
protocol AnyContainer {
var any: Any { get }
}
extension GenericContainer: AnyContainer {
var any: Any {
x
}
}
compiles with no errors.
Generics in Swift do not support covariance .
1 Like
Lantua
February 3, 2021, 3:24pm
3
It's not about generics:
protocol AnyContainer {
var x: Any { get }
}
// error: type 'IntContainer' does not conform to protocol 'AnyContainer'
// note: candidate has non-matching type 'Int'
// note: protocol requires property 'x' with type 'Any'; do you want to add a stub?
struct IntContainer: AnyContainer {
let x: Int
}
PS
Related thread–Protocol property requirements do not support subtyping?
2 Likes
I see, thanks @Lantua . Here are the relevant bugs.
opened 09:07AM - 12 Jan 16 UTC
bug
Compiler
| | |
|------------------|-----------------|…
|Previous ID | SR-522 |
|Radar | rdar://problem/17906373 |
|Original Reporter | hlovatt (JIRA User) |
|Type | Bug |
Attachment: [Download](https://user-images.githubusercontent.com/2727770/164961116-554638d7-08cf-46cb-8691-365c1d00ed8a.gz)
<details>
<summary>Environment</summary>
Xcode 7.2
</details>
<details>
<summary>Additional Detail from JIRA</summary>
| | |
|------------------|-----------------|
|Votes | 17 |
|Component/s | Compiler |
|Labels | Bug |
|Assignee | samballantyne (JIRA) |
|Priority | Medium |
md5: 25aabb7ea4b4c8e107945dc27bb41814
</details>
**is duplicated by**:
* [SR-629](https://bugs.swift.org/browse/SR-629) Protocol composition types should be covariant with composing protocols for protocol conformance
* [SR-731](https://bugs.swift.org/browse/SR-731) Covariant overrides don't work with protocols
* [SR-733](https://bugs.swift.org/browse/SR-733) Contravariant overrides on return type don't work with protocols
* [SR-1950](https://bugs.swift.org/browse/SR-1950) Read-only protocol property requirements not satisfied by subtypes, when they should be
* [SR-2306](https://bugs.swift.org/browse/SR-2306) Should a noescape closure be a subtype of an escaping closure?
* [SR-4103](https://bugs.swift.org/browse/SR-4103) Allow protocol conformance by promoting property getter of type T to T?
* [SR-4161](https://bugs.swift.org/browse/SR-4161) Subtyping of Optionals incomplete
* [SR-4694](https://bugs.swift.org/browse/SR-4694) Subtyping Properties and Return Types for Protocol Conformance
* [SR-5266](https://bugs.swift.org/browse/SR-5266) Swift protocol doesn't compile when using a subclass in the property implementation
* [SR-6187](https://bugs.swift.org/browse/SR-6187) Swift does not infer the signature automatically
* [SR-6220](https://bugs.swift.org/browse/SR-6220) Optional promotion when conforming to protocol
* [SR-7312](https://bugs.swift.org/browse/SR-7312) Conforming to protocol using constrained generic
**relates to**:
* [SR-5858](https://bugs.swift.org/browse/SR-5858) Incorrectly implementing LocalizedError protocols does not result in an error at compile time but an incorrect error localized description
**Issue Description:**
Currently Swift is inconsistent on how it handles covariant return types, consider the code below:
``` none
class Top {}
class Bottom: Top {}
protocol P {
func mT() -> Top
typealias A: Top
func mA() -> A
}
struct S: P {
func mT() -> Top { // Must be `Top` otherwise *type's declaration* gets error "does not conform to protocol P"
return Bottom()
}
typealias A = Top
func mA() -> Top { // Must be `Top` otherwise *type's declaration* gets error "does not conform to protocol P"
return Bottom()
}
}
class BC<G: Top>: P {
func mG() -> G {
fatalError("Needs to be overridden")
}
func mT() -> Top { // Must be `Top` otherwise *type's declaration* gets error "does not conform to protocol P"
fatalError("Needs to be overridden")
}
typealias A = Top
func mA() -> Top { // Must be `Top` otherwise *type's declaration* gets error "does not conform to protocol P"
fatalError("Needs to be overridden")
}
}
class DC: BC<Top> {
override func mG() -> Bottom { // Can be Bottom!
return Bottom()
}
override func mT() -> Bottom { // Can be ottom!
return Bottom()
}
override func mA() -> Bottom { // Can be Bottom!
return Bottom()
}
}
```
The behaviour is odd in that if a class overrides a method from another class then covariant return types are allowed. However if a class or struct implements a method from a protocol then it can't implement with a covariant return type.
When you implement a method with a protocol extension you get similar behaviour in that a class that overrides the already implemented behaviour can now have a covariant return type:
``` none
protocol PE {
func mT() -> Top
}
extension PE {
func mT() -> Top { // Must be `Top` otherwise **compiler crashes** (seg. fault: 11)
fatalError("Needs to be overridden")
}
}
class CE: PE {
func mT() -> Bottom { // Can be Bottom!
return Bottom()
}
}
```
Chris Lattner on swift-evolution suggested that this is a bug and in all cases covariant return types should be allowed.
Above code in attached project.
opened 08:00PM - 30 Jun 16 UTC
closed 09:00PM - 30 Jun 16 UTC
bug
| | |
|------------------|-----------------|…
|Previous ID | SR-1950 |
|Radar | None |
|Original Reporter | jmeggesto (JIRA User) |
|Type | Bug |
|Status | Resolved |
|Resolution | Duplicate |
Attachment: [Download](https://user-images.githubusercontent.com/2727770/164961456-9ecbcf9c-c10a-47bf-9e1d-3e23a2044712.gz)
<details>
<summary>Additional Detail from JIRA</summary>
| | |
|------------------|-----------------|
|Votes | 0 |
|Component/s | |
|Labels | Bug |
|Assignee | None |
|Priority | Medium |
md5: eb8a5cbd4c2b9bb32829979d579cd44b
</details>
**duplicates**:
* [SR-522](https://bugs.swift.org/browse/SR-522) Protocol funcs cannot have covariant returns
**Issue Description:**
Protocol property requirements are not satisfied by subtypes of the property type.
For example: a protocol that requires a property of UIResponder? will not be satisfied with an implementation of that property as UIViewController?, or UIView? and will instead require the base UIResponder? to fulfill the requirement.
See attached screenshot.