Home > database >  Why in kotlin "something != null || return" does not perform smartcast, but "if (some
Why in kotlin "something != null || return" does not perform smartcast, but "if (some

Time:11-02

Given a function. for example:

suspend fun getUser(userId: Int): User? {
    val result: UserApiResult? = fetchTheApi(userId)

    //result != null || return null    // Not smartcast
    if (result == null) return null    // Will make an smartcast of result from UserApiResult? to UserApiResult

    return User(result.email, result.name) 
}

Inside my IDE, specifically Android Studio. The first condition won't perform a smartcast even though it visibly does the same thing as the second condition (unless it's doing some dark things under the hood).

CodePudding user response:

There is no good technical reason for smart casting to not take effect.

But it is jankier than you are giving it credit for. The only reason result != null || return null compiles is because return null has type Nothing and you can coerce Nothing to anything (in this case: Boolean).

The compiler should be able to reason that result != null as otherwise we would have obtained an instance of Nothing (which is impossible). But I'm personally glad I'll never have to see || return null in code review and I imagine the reasons for this not working are not a mistake by the Koltin devs.


Speculation on my part is that the compiler coerces the Nothing from return null to Boolean and loses the semantics of that branch being impossible to return from.

CodePudding user response:

I think it's just a limitation of the current compiler. Building that code fails with the current compiler, but if you switch to the new K2 compiler (still in Alpha at the moment) compilation succeeds.

Example:

fun returnSomething(): String? = null

fun doSomething(): String? {
    val result: String? = returnSomething()

    result != null || return null

    return result.length.toString()
}

fun main() {
    println(doSomething())
}

Build output:

Kotlin: kotlinc-jvm 1.7.10 (JRE 1.8.0_212-b10)
Kotlin: ATTENTION!
This build uses experimental K2 compiler:
-Xuse-k2
Kotlin: performing incremental compilation analysis
Updating dependency information… [coroutines-test]
Running 'after' tasks
Finished, saving caches…
Executing post-compile tasks...
Synchronizing output directories...
01/11/2022, 18:01 - Build completed successfully with 4 warnings in 9 sec, 296 ms
  • Related