Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't Swift automatically convert a generic type parameter to its superclass? [duplicate]

Tags:

generics

swift

Consider the following in Swift:

struct GenericStruct<T> {}
class A {}
class B: A {}

func doSomething() -> GenericStruct<A> {
   return GenericStruct<B>()
}

This gives the error:

Cannot convert return expression of type GenericStruct<B> to return type GenericStruct<A>

But B is a subclass of A.

  • Why can't Swift convert GenericStruct<B> to GenericStruct<A>?
  • What should be done in this scenario?
like image 410
funkybro Avatar asked Nov 29 '22 08:11

funkybro


2 Answers

Swift generics are invariant, meaning that two generic types are unrelated even if their generic type parameters have an inheritance relation. Invariant generic types cannot be cast to each other since they have no inheritance relation to each other.

This means that GenericStruct<B> and GenericStruct<A> are completely unrelated even if B is a subclass of A, hence you cannot cast one to the other.

like image 98
Dávid Pásztor Avatar answered Dec 21 '22 01:12

Dávid Pásztor


Here's a counter example as to what could happen if this were allowed:

struct GenericStruct<T> {
    let value: T
}

class A {}
class B: A {}
class C: A {}

let wrapperOfB: GenericStruct<B> = GenericStruct(value: B())
let wrapperOfA: GenericStruct<A> = wrapperOfB // Suppose GenericStruct<B> was a subtype of GenericStruct<A>
wrapperOfA.value = C() // C is an A, so this should be legal

useB(wrapperOfB.value) // Now what?
like image 25
Alexander Avatar answered Dec 20 '22 23:12

Alexander