# Why !. are required, as the field is never null?

**URL:** <https://discuss.kotlinlang.org/t/why-are-required-as-the-field-is-never-null/22750>\
**Category:** Support\
**Created:** [August 20, 2021, 5:07am UTC](https://discuss.kotlinlang.org/t/why-are-required-as-the-field-is-never-null/22750 "2021-08-20T05:07:33Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![cyanide](https://avatars.discourse-cdn.com/v4/letter/c/7c8e57/32.png) [@cyanide](https://discuss.kotlinlang.org/u/cyanide)\
**Post date:** [August 20, 2021, 5:07am UTC](https://discuss.kotlinlang.org/t/why-are-required-as-the-field-is-never-null/22750/1 "2021-08-20T05:07:33Z")

</div>

I wonder, why Kotlin compiler insists on placing !! after _itemGroup_ in the following code, at to me it looks obvious that the value of _itemGroup_ is never _null_:

```auto
       val itemViewsList = mutableListOf<TextView>()
       val viewGroupQueue = java.util.LinkedList<ViewGroup>()
       var itemValue = 0

        // Collect text items using breadth first algorithm
        var itemGroup: ViewGroup? = this
        do {
            for (index in 0 until itemGroup!!.childCount) {
                val item = itemGroup!!.getChildAt(index)
                if (item is ViewGroup)
                    viewGroupQueue.add(item)
                else
                if (item is TextView) {
                    item.setText((++itemValue).toString())
                    itemViewsList.add(item)
                }
            }
            itemGroup = viewGroupQueue.poll()
       } while (itemGroup != null)

```

---

<div class="post-metadata">

**Author:** ![Loke](https://avatars.discourse-cdn.com/v4/letter/l/c68b51/32.png) [@Loke](https://discuss.kotlinlang.org/u/Loke)\
**Post date:** [August 20, 2021, 5:54am UTC](https://discuss.kotlinlang.org/t/why-are-required-as-the-field-is-never-null/22750/2 "2021-08-20T05:54:53Z")

</div>

The actual reason for the message from the compiler is that you have declared the variable to be of type `ViewGroup?`. This means that the variable can be null. Whether or not the variable ever actually receives the value null doesn’t actually matter. And while it may be clear to you in this particular case that it’ll never happen, it cannot be proven in the general case, so the compiler relies on the declaration as any other approach would be inconsistent.

---

<div class="post-metadata">

**Author:** ![broot](https://avatars.discourse-cdn.com/v4/letter/b/a88e57/32.png) [@broot](https://discuss.kotlinlang.org/u/broot)\
**Post date:** [August 20, 2021, 10:42am UTC](https://discuss.kotlinlang.org/t/why-are-required-as-the-field-is-never-null/22750/3 "2021-08-20T10:42:55Z")

</div>

Actually, OP’s question makes a lot of sense. In Kotlin we have smart casts and they are… well, pretty smart. Example above doesn’t seem like too complicated to be properly supported by smart casts.

I tried to understand why smart casts don’t cover this, so I ran some tests and I’m surprised with results. I don’t know why some trivial cases are not covered by smart casts. For example:

```
var foo: String? = "foo"
foo.length // error

```

Here, `foo` is not smart-casted to `String`. But here it does:

```
var foo: String?
foo = "foo"
foo.length // ok

```

Condition in `while` is used for smart casts:

```
var foo: String? = null
while (foo != null) {
    foo.length // ok
}

```

Also, it seems smart casts can merge from two control flow branches:

```
var foo : String? = null

if (cond) {
    foo = "foo"
} else {
    foo = "bar"
}

foo.length // ok

```

But `do ... while` does not work as expected:

```
var foo: String?
foo = "foo"
foo.length // ok

do {
    foo.length // error
    foo = null
} while (foo != null)

```

Code at the start of `do ... while` block is a merge of the code above the loop and from the code at the end of the loop. In both of these places `foo` can be smart-casted to `String`, but for some reason it does not merge similarly to `if ... else` case.

Either I miss something or smart casts are still pretty new and they don’t support many cases that they really should.

For now you can replace `do ... while` with `while`. You will perform one redundant null check, but you won’t need to use `!!` anymore.

---

<div class="post-metadata">

**Author:** ![tothiz](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/tothiz/32/10355_2.png) [@tothiz](https://discuss.kotlinlang.org/u/tothiz)\
**Post date:** [August 22, 2021, 7:29am UTC](https://discuss.kotlinlang.org/t/why-are-required-as-the-field-is-never-null/22750/4 "2021-08-22T07:29:09Z")

</div>

I think this is actually how it is supposed to work in the case of declaration:

```kotlin
var foo: String? = "foo"
foo.length // error

```

Here you explicitly clear the information that this is not null. The type declaration overrides everything the compiler knows about the type of the value.

* * *

```kotlin
var foo: String?
foo = "foo"
foo.length // ok

```

Here you start with `String?` then assignment changes the “effective” type from `String?` to `String`.

* * *

As for the difference between the `while` and the `do...while`, it indeed feels like an inconsistency.

I think this is because the actual check might be hard to implement in the compiler. The smart casts are not just about nulls. They are more like type intersections (I guess).

For example:

```kotlin
open class S

class A : S() {
    val a = "A"
}

class B : S()

fun a() {
    var foo: S
    foo = A()

    foo.a // ok
    
    do {
        foo.a // error
        foo = B()
    } while (foo is A)
}

```

This behaves exactly the same as the null check. If you change the `do...while` to `while` it shows no error.

As I see in the case of `do...while` there are two condition sets the code has: one before the first run of the block and for the subsequent runs. In these examples these are the same, but in some cases they might be in conflict.

Truth to be told, I’m just thinking out loud. 😃

---

<div class="post-metadata">

**Author:** ![broot](https://avatars.discourse-cdn.com/v4/letter/b/a88e57/32.png) [@broot](https://discuss.kotlinlang.org/u/broot)\
**Post date:** [August 22, 2021, 9:47pm UTC](https://discuss.kotlinlang.org/t/why-are-required-as-the-field-is-never-null/22750/5 "2021-08-22T21:47:17Z")

</div>

> [@tothiz](#):
>
> Here you explicitly clear the information that this is not null. The type declaration overrides everything the compiler knows about the type of the value.

Yes, I know this is probably what is happening internally. Still, I’m not convinced it should behave like this. I guess for most developers `val foo: String = "foo"` is just a short way of declaring and initializing a variable and they would be really surprised if I told them this one-liner is not exactly the same as its two-lines alternative.

Besides, I think it is almost never beneficial to not smart cast - it could/should be performed whenever possible.

> [@tothiz](#):
>
> The smart casts are not just about nulls. They are more like type intersections (I guess).

Yes, they are. In fact, smart casts for nullability and for subtypes are exactly the same, because nullability in Kotlin is represented by the type system. `String` is a subtype of `String?`, so smart casting of `String?` to `String` is very similar to smart casting `S` to `A`.

But I don’t see why this is a problem. We know how to merge two types, we do this all the time both in Kotlin and Java. We just need to find a closest common supertype. Kotlin does this e.g. for type inference. Naive implementation could just merge `A` + `A` into `A` and any other combination would disable smart casting.

I ran some additional tests for types merging and results are even more surprising, at least to me 😉

```
fun test1(cond: Boolean) {
    var any: Any
    var a: A

    any = if (cond) C() else D()
    any.b // ok, Any smart casted to B

    a = if (cond) C() else D()
    a.b // error, just A

    val b = if (cond) C() else D()
    a = b
    a.b // ok, A smart casted to B
}

open class A
open class B : A() {
    val b = "b"
}
open class C : B()
open class D : B()

```

There are two conclusions. First, regular type inference uses more advanced techniques of inferring the type than smart casts. Assigning a value to intermediate variable allowed to guess the type more accurately than when assigning it directly. Regarding the first and second example - I have no idea, it doesn’t make any sense to me that `Any` was smart casted to `B`, but `A` wasn’t.

Regarding `do ... while` and loops in general I think the problem may be different. If we would like to infer types at the beginning of the loop by utilizing type information at the end of the loop, then we would get into two-way dependency problem. This is definitely solvable, but it is not as trivial as type merging in simple `if ... else` case.

---

<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 22, 2021, 10:14pm UTC](https://discuss.kotlinlang.org/t/why-are-required-as-the-field-is-never-null/22750/6 "2021-08-22T22:14:05Z")

</div>

> [@broot](#):
>
> Besides, I think it is almost never beneficial to not smart cast - it could/should be performed whenever possible.

I feel like there’s some situations where it _really shouldn’t_ be performed. For example. let’s say for now you’re using an ArrayList as your “list of choice” inside of your function, but then later on you want to change it to a different `List` implementation. Now, if the value is auto smart-casted, then suddenly you’ll get missing calls that seemed to originate out of nowhere. I personally feel like whenever a developer specifically adds a type, then they absolutely want that to be the type of the declaration, since Kotlin already has type inference and so they could just remove the specific type.

---

<div class="post-metadata">

**Author:** ![broot](https://avatars.discourse-cdn.com/v4/letter/b/a88e57/32.png) [@broot](https://discuss.kotlinlang.org/u/broot)\
**Post date:** [August 22, 2021, 10:30pm UTC](https://discuss.kotlinlang.org/t/why-are-required-as-the-field-is-never-null/22750/7 "2021-08-22T22:30:43Z")

</div>

Hmm, good point. Maybe you are both right. This case I’m talking about (which existed in OP’s example) is actually pretty rare, it happens only if:

1. We declare a `var` (not `val`).
2. We initially set it to some subtype.
3. Later, we would like to reassign it to another type.
4. We would like to recognize the variable initially as the subtype.

In such a specific case it probably makes sense to split declaration and assignment into two lines.
