# Covariance / Contravariance

**URL:** <https://forums.swift.org/t/covariance-contravariance/39635>\
**Category:** Using Swift\
**Tags:** generics\
**Created:** [August 23, 2020, 3:20pm UTC](https://forums.swift.org/t/covariance-contravariance/39635 "2020-08-23T15:20:23Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![cristoppotelli](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/cristoppotelli/32/13773_2.png) [@cristoppotelli](https://forums.swift.org/u/cristoppotelli)\
**Post date:** [August 23, 2020, 3:20pm UTC](https://forums.swift.org/t/covariance-contravariance/39635/1 "2020-08-23T15:20:24Z")

</div>

Hello everybody, I was kind of experimenting with covariance and contravariance in Swift to better understand this topic, and I run into something I can't understand, maybe I'm missing something here.

Suppose we have:

```
class Foo<T> where T : Bar {} 
class Bar {}
class BarChild : Bar {}

let array: Array<Bar> = Array<BarChild>()

```

The above assignment compiles fine, and thus I may assume that Swift types are contravariant in their generic signature, but then I tried this:

```
let instance: Foo<Bar> = Foo<BarChild>()

```

I expected the last assignment to work as the other one, but it doesn't, why is that?  
Are just standard library types able to be contravariant in their generic types?

I then tried:

```
class FooChild<C> : Foo<C> where C : Bar
let childInFather: Foo<Bar> = FooChild<Bar>; Ok

```

For the sake of brevity, this is the only assignment working (reversing Child - Father relationship in both enclosing and generic types don't compile), hence I assume that Swift generic types, when of reference kind (classes), are invariant in their generic argument but contravariant in their container type (the holder of the generic argument to be clear).

If I got something wrong please feel free to correct me, just seeking for somebody more educated than me 🙂

---

<div class="post-metadata">

**Author:** ![jayton](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jayton/32/5592_2.png) [@jayton](https://forums.swift.org/u/jayton)\
**Post date:** [August 23, 2020, 3:23pm UTC](https://forums.swift.org/t/covariance-contravariance/39635/2 "2020-08-23T15:23:40Z")

</div>

> [@cristoppotelli](#):
>
> Are just standard library types able to be contravariant in their generic types?

Yep.

---

<div class="post-metadata">

**Author:** ![cukr](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/cukr/32/889_2.png) [@cukr](https://forums.swift.org/u/cukr)\
**Post date:** [August 23, 2020, 3:43pm UTC](https://forums.swift.org/t/covariance-contravariance/39635/3 "2020-08-23T15:43:20Z")

</div>

As Jayton said, some of the standard library types are special cases and don't behave like most other types.

If you want to understand complex relationships between types, I would recommend checking out awesome document [swift/DynamicCasting.md at main · apple/swift · GitHub](https://github.com/apple/swift/blob/master/docs/DynamicCasting.md) written by @tbkka last week which is a description how dynamic cast operators (as? as! is) behave in swift today. It talks about dynamic casts, and not static casts like the one you're interested in, but should highlight some sharper edges.

---

<div class="post-metadata">

**Author:** ![cristoppotelli](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/cristoppotelli/32/13773_2.png) [@cristoppotelli](https://forums.swift.org/u/cristoppotelli)\
**Post date:** [August 23, 2020, 4:45pm UTC](https://forums.swift.org/t/covariance-contravariance/39635/4 "2020-08-23T16:45:29Z")

</div>

Interesting, thank you

---

<div class="post-metadata">

**Author:** ![young](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/young/32/7878_2.png) [@young](https://forums.swift.org/u/young)\
**Post date:** [August 24, 2020, 12:11am UTC](https://forums.swift.org/t/covariance-contravariance/39635/5 "2020-08-24T00:11:47Z")

</div>

> [@How are \`Array\` and \`Value\` covariant](https://forums.swift.org/t/how-are-array-and-value-covariant/36064):
>
> I just noticed that Array and Value are covariant, but general generic placeholders are invariant: class Base {} class Derived: Base {} struct Foo\<Value\> {} // Ok let array: Array\<Base\> = Array\<Derived\>() // Fail let foo: Foo\<Base\> = Foo\<Derived\>() You can even down cast [Base] to [Derived] using as! with appropriate values. Is this a special behaviour, or is there a way to annotate it?

> **[Covariance and Contravariance in Swift](https://medium.com/@aunnnn/covariance-and-contravariance-in-swift-32f3be8610b9)**
>
> First let’s check if you need this article or not:

---

<div class="post-metadata">

**Author:** ![tbkka](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tbkka/32/7532_2.png) [@tbkka](https://forums.swift.org/u/tbkka)\
**Post date:** [August 24, 2020, 4:27pm UTC](https://forums.swift.org/t/covariance-contravariance/39635/6 "2020-08-24T16:27:22Z")

</div>

Swift has special case support for a few standard library types (Optional, Array, Set, Dictionary). But it would require language changes to expand that to support user-defined types.

In particular, the compiler currently is not able to tell whether your `Foo<>` type is actually covariant in its generic type. (Not all generic types are; it depends on how your `Foo` type uses the generic argument.)
