3

I am trying check nullable object with extension function, but smart casting not work after calling this function.

fun <T> T?.test(): T = this ?: throw Exception()

val x: String? = "x"
x.test()
x.length // Only safe (?.) or non-null asserted (!!) calls are allowed on a nullable receiver of type String?

Is it a Kotlin bug? If not, why there is no implicit casting?

Alexey
  • 2,980
  • 4
  • 30
  • 53
  • 1
    Your null test is hidden behind your function. For this to work, your function has to employ a contract. This function is redundant to the `!!` operator, which would provide you the smart cast. – Tenfour04 Apr 08 '20 at 05:00
  • 7
    It's because the extension function returns the non nullable object, but you're not reassigning it to `x`. If you had `var x` and you reassign it as `x = x.test()`, then it would work. – Madhu Bhat Apr 08 '20 at 05:03
  • https://stackoverflow.com/questions/57670014/retain-smartcast-when-creating-custom-extension related – Adam Apr 08 '20 at 07:17

1 Answers1

2

As @Madhu Bhat mentioned in comment above, your variable 'x' is still nullable. You may use your function simply like this:

x.test().length

Otherwise you can check for null by following inline function and then perform any functions directly on the variable. (Note the usage of 'contract' and annotations '@ExperimentalContracts')

@ExperimentalContracts
fun <T> T?.notNull(): Boolean {

    contract {
        returns(true) implies (this@notNull != null)
    }

    return this != null
}

Now you can use this function like this

if(x.notNull()){
  x.length
}

But its not seems so useful if your using this function just to check nullability.

Check here to know more about Kotlin contracts

Niroshan
  • 1,174
  • 1
  • 12
  • 30
  • This kind of code seems to not compile for me: https://stackoverflow.com/questions/75178295/kotlin-contracts-not-working-for-null-check-in-extension-function I have code snipits here. It works when I use a traditional function, but not an extension. – rexar5 Jan 19 '23 at 21:14