# Generic variance: can't use var with \<out T\> and can't use val with \<in T\>?

**URL:** <https://discuss.kotlinlang.org/t/generic-variance-cant-use-var-with-out-t-and-cant-use-val-with-in-t/18868>\
**Category:** Support\
**Created:** [August 22, 2020, 12:48am UTC](https://discuss.kotlinlang.org/t/generic-variance-cant-use-var-with-out-t-and-cant-use-val-with-in-t/18868 "2020-08-22T00:48:26Z")\
**Posts on this page:** 10\
**Page:** 2

<div class="post-metadata">

**Author:** ![kyay10](https://avatars.discourse-cdn.com/v4/letter/k/c57346/32.png) [@kyay10](https://discuss.kotlinlang.org/u/kyay10)\
**Post date:** [August 25, 2020, 11:14pm UTC](https://discuss.kotlinlang.org/t/generic-variance-cant-use-var-with-out-t-and-cant-use-val-with-in-t/18868/21 "2020-08-25T23:14:39Z")

</div>

> [@Mervil](#):
>
> Like looking at the object through a narrowed window

This is literally it lol.

> [@Mervil](#):
>
> Does this change `<T>` at all from `<Any>` to `<String>` , so that the `content` property for `contString` would of type `String` now, instead of `Any` ?  
> More specifically, are `cont` and `contString` still referencing the same object, or is `contString` referencing a different object that was redefined as a `String` type using the `Container<Any>` object as a template?

Yes, they are referencing the same value. The thing about generics is that they are kind of a “contract-y” thing, i.e. the Container class actually has no idea what `T` is. Even if we assume that it did know what T is (which it does in .NET languages like C#, but sadly not in Kotlin), it would only know what T was when the object was created (i.e. T would basically kinda be like a val constructor parameter). Casting basically just allows you to look at an object in a more constrained or less constrained way, and so it **never** , and I mean never, mutates the object or copies it or anything, it just gives you a different “perspective” of the object.

---

<div class="post-metadata">

**Author:** ![Mervil](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/mervil/32/7785_2.png) [@Mervil](https://discuss.kotlinlang.org/u/Mervil)\
**Post date:** [August 25, 2020, 11:51pm UTC](https://discuss.kotlinlang.org/t/generic-variance-cant-use-var-with-out-t-and-cant-use-val-with-in-t/18868/22 "2020-08-25T23:51:43Z")

</div>

Oh, the horse moved again! Beat it some more!

Ok. I’ve been testing this stuff out in my own code. I felt that `Any`, representing everything, was too general for me to see how things were working. I made up this code:

```
open class AnyAnimal
class Dog : AnyAnimal()
class Cat : AnyAnimal()

class Container<out T>(val species: T)

fun main() {
    val kennel: Container<Dog> = Container(Dog())
    val zoo : Container<AnyAnimal> = kennel

    val animals : AnyAnimal = zoo.species

    if (animals is Dog) {
        println("It's a doggy!")
    }
}

```

The **`val`** `animals` is type `AnyAnimal`. Yet, this if statement here `(animals is Dog)` does result to true. Yet if I change it to `(animals is Cat)`, it is false, and the println output doesn’t happen.

I found this interesting. A `Dog` certainly is an `AnyAnimal`; I didn’t think `AnyAnimal` would also be a `Dog`.

So, because `kennel`, of type `Container<Dog>` is cast to `zoo`, of type `Container<AnyAnimal>`, the `animals` `val` and therefore `zoo.species` has 2 types? And that is what happens with casting?

---

<div class="post-metadata">

**Author:** ![kyay10](https://avatars.discourse-cdn.com/v4/letter/k/c57346/32.png) [@kyay10](https://discuss.kotlinlang.org/u/kyay10)\
**Post date:** [August 26, 2020, 12:10am UTC](https://discuss.kotlinlang.org/t/generic-variance-cant-use-var-with-out-t-and-cant-use-val-with-in-t/18868/23 "2020-08-26T00:10:39Z")

</div>

You’re almost there. There are basically 2 different types of types (types of types? kinds of types I guess is the better way to put it). Those 2 are compile time and runtime types. During compile time, you only have the times that are specifically declared in your code. Safe casts are safe because they are guaranteed at compile time. During runtime though, you can see what every object’s real type is, but as a downside you can’t see the type parameters of an object. `animals is Dog` is a runtime check. It basically checks if the real type of animals is actually a Dog. This has no realtion whatsoever to the fact that `zoo.species` is an AnyAnimal. `zoo` could literally be a `Container<Any>` and the code would still work in the same way. The reason behind that is that zoo is referencing the `Container(Dog))` that you created before, and so when you check whether `zoo.species` is a Dog, your program checks during runtime whether the reference that zoo.species has is of type `Dog`, and in this case it is.

---

<div class="post-metadata">

**Author:** ![kyay10](https://avatars.discourse-cdn.com/v4/letter/k/c57346/32.png) [@kyay10](https://discuss.kotlinlang.org/u/kyay10)\
**Post date:** [August 26, 2020, 12:13am UTC](https://discuss.kotlinlang.org/t/generic-variance-cant-use-var-with-out-t-and-cant-use-val-with-in-t/18868/24 "2020-08-26T00:13:17Z")

</div>

`is` basically allows you to check if a cast would actually be legal or not. Because Kotlin also has smartcasting, inside of the `if (animals is Dog)` block, you can use animals as a `Dog` object, because the compiler knows that during runtime this block of code will only run if animals is indeed a Dog. You couldn’t use animals as a Dog before doing the check tho, because the compiler has no way of guaranting that an AnyAnimals would definitely be a Dog without knowing that that specific instance of AnyAnimals (which is animals) is a Dog.

---

<div class="post-metadata">

**Author:** ![fatjoe79](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/fatjoe79/32/4221_2.png) [@fatjoe79](https://discuss.kotlinlang.org/u/fatjoe79)\
**Post date:** [August 26, 2020, 6:43am UTC](https://discuss.kotlinlang.org/t/generic-variance-cant-use-var-with-out-t-and-cant-use-val-with-in-t/18868/25 "2020-08-26T06:43:24Z")

</div>

> [@Mervil](#):
>
> I think I’ve confused myself again. I know I’m thinking about this too hard.
> 
> ```auto
> class Container<in T>(val content: T) //Compiler error right here
> 
> fun main() {
> val cont = Container<Any>(Any()) // Just creating a new Any object for this example
> val contString: Container<String> = cont //This is totally legal because in guarantees downcasting safely
> val str: String = contString.content //Whoops, you are now trying to cast an Any to a String.
> }
> 
> ```

Why are you ignoring the compiler error in the first line? What you need to understand is that not every class can be contravariant or covariant.

The compiler will check the structure of your class and will allow or disallow it to have “in” or “out” type parameters.

Generally, classes that have T only in “in” positions are allowed to be contravariant on T. Classes that have T only in “out” positions can be covariant on T. Classes that have T in both positions can neither be covariant or contravariant.

**In your example, this class has T in an “out” positions (a property accessor). Therefore it is not allowed to declare “in T”.**

And there are good reasons for this, too. You have found the reasons yourself. This very example shows why this class cannot be contravariant. If it were contravariant, there would be a failure in the last line of this example. But lucky for us, the compiler prevents this because the first line is not accepted by the compiler.

The rest of your questions in this post are invalid, because there cannot be a situation in which they could be asked (the compiler prevents such situations).

Here is an example of a class that is allowed to be contravariant:

```
class Consumer<in T> {
   fun consume(t: T) // T is used in "in" position only
}

```

---

<div class="post-metadata">

**Author:** ![Mervil](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/mervil/32/7785_2.png) [@Mervil](https://discuss.kotlinlang.org/u/Mervil)\
**Post date:** [August 26, 2020, 5:29pm UTC](https://discuss.kotlinlang.org/t/generic-variance-cant-use-var-with-out-t-and-cant-use-val-with-in-t/18868/26 "2020-08-26T17:29:45Z")

</div>

This code was given as an example of why you can’t use a ‘val’ with \<in\> to help me understand the concept. I’m not ignoring the error; the error was introduced intentionally to illustrate the point.  
I don’t think my questions are invalid. I’m trying to understand the underlying concepts, not trying to get intentionally broken code to work. Just because you understand it well, and I don’t, does NOT make my questions invalid.

---

<div class="post-metadata">

**Author:** ![fatjoe79](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/fatjoe79/32/4221_2.png) [@fatjoe79](https://discuss.kotlinlang.org/u/fatjoe79)\
**Post date:** [August 26, 2020, 5:38pm UTC](https://discuss.kotlinlang.org/t/generic-variance-cant-use-var-with-out-t-and-cant-use-val-with-in-t/18868/27 "2020-08-26T17:38:08Z")

</div>

I might have misunderstood your intentions in that post, and I am sorry for that. I do not think that your questions are invalid in general. Quite contrary.

I still think though that those questions should be discussed in the context of valid code. This is also important for preventing potential misunderstanding with future readers of these posts.

---

<div class="post-metadata">

**Author:** ![Wasabi375](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/wasabi375/32/4741_2.png) [@Wasabi375](https://discuss.kotlinlang.org/u/Wasabi375)\
**Post date:** [August 26, 2020, 6:52pm UTC](https://discuss.kotlinlang.org/t/generic-variance-cant-use-var-with-out-t-and-cant-use-val-with-in-t/18868/28 "2020-08-26T18:52:55Z")

</div>

> [@fatjoe79](#):
>
> I still think though that those questions should be discussed in the context of valid code.

Normally I agree with that. However to understand restrictions you have to understand what they are suppost to prevent. Therefore when looking at variance it is a necesseary thought experiment to ignore variance to see what kind of errors that would create. I guess in this case it’s possible to use the `UnsafeVariance` anotation 😇

```auto
class Container<in T>(var content: @UnsafeVariance T) 

fun main() {
/* 1 */ val cont = Container<Any>(5) // Just creating a new Any object for this example
/* 2 */ val contString: Container<String> = cont //This is totally legal because in guarantees downcasting safely
/* 3 */ val str: String = contString.content //Whoops, you are now trying to cast an Any to a String.
}

```

If we look at what happens in the main method it’s something like:

1. create a container with generic type any and fill it with a value of 5  
This means that the we save a value of type `Int` inside a field of type `Any`. So far so good.
2. Cast the container from `Container<Any>` to `Container<String>`. This means that `content` still contains the value `5` of type `Int` but our program now thinks it’s a `String`. This is bad, but it won’t raise any errors at this point. If we were to cast this back to a `Container<Any>` or ` Container<Int>` we would never notice something is wrong.
3. When we access `contSTring.content` this is basically the same as trying `contString.content as String`. The value of `content` is 5 but the program thinks it’s a `String` which will result in an exception.

For that reason you aren’t allowed to use `in T` as a return type (or the type of a property). Same goes the other way round. You can’t use `out T` is a parameter to a function (or a `var` property) since you can create a similar situation where this would result in a typecast exception.

* * *

To prevent the question about the `UnsafeVariance` annotation I used: There are some few exceptions to this rule, eg. equality checks. This annotation allows for functions like `List<T>.contains(value: @UnsafeVariance T)`. `T` shouldn’t be allowed in an `in` position for `List`s but in this case it’s ok.  
This annotation should still only be used **very cautiously** and if you really understand how generics work and are implemented on each platform(jvm/js/native).

---

<div class="post-metadata">

**Author:** ![Mervil](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/mervil/32/7785_2.png) [@Mervil](https://discuss.kotlinlang.org/u/Mervil)\
**Post date:** [August 26, 2020, 6:58pm UTC](https://discuss.kotlinlang.org/t/generic-variance-cant-use-var-with-out-t-and-cant-use-val-with-in-t/18868/29 "2020-08-26T18:58:34Z")

</div>

> [@kyay10](#):
>
> This has no realtion whatsoever to the fact that `zoo.species` is an AnyAnimal. `zoo` could literally be a `Container<Any>` and the code would still work in the same way.

Ah, so you are saying that because `zoo` references `kennel`, that `zoo` is referencing an object of type `Container<Dog>`, even though zoo is defined as a` Container<AnyAnimal>`. `zoo` could be defined as a `Container<Any>`, but would still be referencing a `Container<Dog>`. So `animal` is therefore referencing a `Dog` when it access `zoo.species`. Therefore, of course `(animal is Dog)` will be true. And as a `Dog` is a subtype of `AnyAnimal` and also a subtype of `Any` by definition, it will always be true anyway that `(animal is AnyAnimal)` or `(animal is Any)`. Like so:

```
open class AnyAnimal
class Dog : AnyAnimal()
class Cat : AnyAnimal()

class Container<out T>(val species: T)

fun main() {
    val kennel: Container<Dog> = Container(Dog())
    val zoo : Container<Dog> = kennel

    val animals : Dog = zoo.species

    if (animals is AnyAnimal) {
        println("A Dog is AnyAnimal!")
    }
}

```

---

<div class="post-metadata">

**Author:** ![akurczak](https://avatars.discourse-cdn.com/v4/letter/a/f07891/32.png) [@akurczak](https://discuss.kotlinlang.org/u/akurczak)\
**Post date:** [August 28, 2020, 10:32pm UTC](https://discuss.kotlinlang.org/t/generic-variance-cant-use-var-with-out-t-and-cant-use-val-with-in-t/18868/30 "2020-08-28T22:32:07Z")

</div>

I see there are some great explanations in this topic, but I thought I would drop this picture, as it visualizes variance in quite an intuitive way:

 ![6MQ16](https://us1.discourse-cdn.com/flex019/uploads/kotlinlang/original/2X/d/de2857c82da14229f879c9b5e50b3e112c3c1951.png)

Source: [scala - How to check covariant and contravariant position of an element in the function? - Stack Overflow](https://stackoverflow.com/a/48858344)

I would also recommend looking into it, as it supports the image with code examples (in Scala, but they should be understandable) and comments.

[Previous page](https://discuss.kotlinlang.org/t/generic-variance-cant-use-var-with-out-t-and-cant-use-val-with-in-t/18868.md?page=1)
