Combine null safety and assertNotNull
Unfortunately, the bodies of the functions that you call, including inline functions, are not used for smart casts and nullability inference.
There's not much in your code that can be improved, and I would only suggest one thing: you can use the Elvis operator with a Nothing
function for those assertion statements. The control flow analysis takes into account the branches resulting into Nothing
and infers nullability from that:
fun failOnNull(): Nothing = throw AssertionError("Value should not be null")
val test: Foo? = foo()
test ?: failOnNull()
// `test` is not-null after that
This can be written without a function as well: test ?: throw AssertionError("...")
, because a throw
expression also has type Nothing
.
Speaking of a more general case of failing an assertion, one might use a fail(...): Nothing
function, which provides a bonus hint for the control flow analysis as well. The JUnit Assert.fail(...)
is not a Nothing
function, but you can find one in the kotlin-test-junit
module or write your own one.
test as? SomeType ?: fail("`test` should be an instance of SomeType")
// smart cast works here, `test` is `SomeType`
The kotlin.test library comes with an easy solution for this:
kotlin.test.assertNotNull()
Because this function implements Kotlin contracts it supports smart casting:
contract { returns() implies (actual != null) }
Example:
fun Foo?.assertBar() {
assertNotNull(this)
assertEquals(this.bar, 0)
}
Just make sure to use the right assertNotNull
import (import kotlin.test.assertNotNull
)!
If you don't already use the kotlin.test
library, add it to your project:
group: 'org.jetbrains.kotlin', name: 'kotlin-test', version: '1.3.11