Let’s say we have piece of code like this
val text : String? = getText()
if (text.isNullOrEmpty()) {
return
}
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.