Why doesn't smart cast use data from in-code contracts?


Let’s say we have piece of code like this

val text : String? = getText()

if (text.isNullOrEmpty()) {

val number = text.toInt()

We know that text is cannot be null at the end, because isNullOrEmpty function causes early exit in null case. Compiler does not seem to know that and reports error that you cannot use toInt() on nullable type.

Now, I understand it is not really feasible for compiler to analyze flow of every function, but std isNullOrEmpty function contains extra lines that describe exactly the fact that returning false means passed String is not null:

public inline fun CharSequence?.isNullOrEmpty(): Boolean {
    contract {
        returns(false) implies (this@isNullOrEmpty != null)

    return this == null || this.length == 0

So why is that info not used to automatically smart cast String? in above example into String ?

I guess one answer would be the fact that contracts are added by humans, so they could be erroneous and cause NPEs, but workaround for this issue is to use !! operator after calling such method, which causes exact same issue.


The contracts are an experimental feature that isn’t enabled yet. See the thread Status of kotlin.internal.contracts? for details.

Just had evil gotcha

Thanks for the answer!