The following is an example of this problem. Why am I unable to invoke supplier using the operator function? If I make supplier non-nullable Supplier<Int> I have no search problem
operator fun <T> Supplier<T>.invoke(): T = this.get()
val supplier: Supplier<Int>? = (Supplier<Int> { 5 })
if (supplier != null) {
// Fails: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Supplier<Int>?
supplier()
supplier.invoke() // fine, smart casts
supplier.get() // fine, smart casts
}
This problem was fixed for me in a later of version of IntelliJ + Kotlin plugin
Related
When checking nullability directly Kotlin is able to find out that x is non-null inside the condidition
fun test(x: X?) {
if(x!=null){
x.callMethod()
}
}
But once I extract the condition into a dedicated method Kotlin is not able to do that anymore:
fun test(x: X?) {
if(isNonNull(x)){
x.callMethod() // Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type X?
}
}
fun isNonNull(x:X?) = x!=null
How can I achieve the same Kotlin behaviour as in the 1st code with extracted methods for conditions?
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?
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
Look at the following code running in Kotlin REPL:
>>> null.takeIf({1==2})
res4: kotlin.Nothing? = null
Why this don't cause NullPointerException?
You code doesn't cause NullPointerException because takeIf is an extension function.
Extension functions are translated into method receiver, first argument being the object you invoked your function on.
So instead of null.takeIf { false } (simplifying your example), you could wonder why the following function doesn't throw a NullPointerException:
fun <T> takeIf(me: T, predicate: (T) -> Boolean): T? {
...
}
Well, for that we need to look into takeIf() implementation (removing annotations and contract):
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
return if (predicate(this)) this else null
}
So, in case your predicate is false (as in your example, 1==2), it just short-circuits and returns null.
What if it's true, then? Will we finally get a NullPointer?
Nope:
val nothing: Nothing? = null.takeIf {
true
}
Kotlin design approach for types aims to eliminate NPEs on purpose. Conditions that might trigger one are limited to, as seen on the docs:
An explicit call to throw NullPointerException();
Usage of the !! operator that is described below;
Some data inconsistency with regard to initialization, such as when:
An uninitialized this available in a constructor is passed and used somewhere ("leaking this");
A superclass constructor calls an open member whose implementation in the derived class uses uninitialized state;
Java interoperation:
Attempts to access a member on a null reference of a platform type;
Generic types used for Java interoperation with incorrect nullability, e.g. a piece of Java code might add null into a Kotlin MutableList, meaning that MutableList should be used for working with it;
Other issues caused by external Java code.
The third option is for NPE-lovers: the not-null assertion operator
(!!) converts any value to a non-null type and throws an exception if
the value is null. We can write b!!, and this will return a non-null
value of b (e.g., a String in our example) or throw an NPE if b is
null:
val l = b!!.length
Thus, if you want an NPE, you can have it, but you
have to ask for it explicitly, and it does not appear out of the blue.
So your code is behaving as expected. See the link for more info
https://kotlinlang.org/docs/reference/null-safety.html
I have the following code fragment:
val foo: String? = null
foo.run { println("foo") }
I have here a nullable variable foo that is actually set to null followed by a nonsafe .run() call.
When I run the code snippet, I get foo printed out despite the fact that the run method is called on a null. Why is that? Why no NullPointerException? Why does compiler allow a nonsafe call on an optional value?
If I pass println(foo), I get a nice juicy null in the console so I think it's safe to assume that foo is actually null.
I believe, there are two things that both might be of some surprise: the language semantics that allow such a call, and what happens at runtime when this code executes.
From the language side, Kotlin allows nullable receiver, but only for extensions. To write an extension function that accepts a nullable receiver, one should either write the nullable type explicitly, or use a nullable upper bound for a type parameter (actually, when you specify no upper bound, the default one is nullable Any?):
fun List<*>?.isEmptyOrNull() = this == null || size == 0 // explicit nullable type
fun <T : CharSequence?> T.nullWhenEmpty() = if ("$this" == "") null else this // nullable T
fun <T> T.identity() = this // default upper bound Any? is nullable
This feature is used in kotlin-stdlib in several places: see CharSequence?.isNullOrEmpty(), CharSequence?.isNullOrBlank(), ?.orEmpty() for containers and String?.orEmpty(), and even Any?.toString(). Some functions like T.let, T.run that you asked about and some others just don't provide an upper bound for the type parameter, and that defaults to nullable Any?. And T.use provides a nullable upper bound Closeable?.
Under the hood, that is, from the runtime perspective, the extension calls are not compiled into the JVM member call instructions INVOKEVIRTUAL, INVOKEINTERFACE or INVOKESPECIAL (the JVM checks the first argument of such calls, the implicit this, for being null and throws an NPE if it is, and this is how Java & Kotlin member functions are called). Instead, the Kotlin extension functions are compiled down to static methods, and the receiver is just passed as the first argument. Such a method is called with the INVOKESTATIC instruction that does not check the arguments for being null.
Note that when a receiver of an extension can be nullable, Kotlin does not allow you to use it where a not-null value is required without checking it for null first:
fun Int?.foo() = this + 1 // error, + is not defined for nullable Int?
To add to what #holi-java said, there is nothing unsafe about your code at all. println("foo") is perfectly valid whether foo is null or not. If you tried something like
foo.run { subString(1) }
it would be unsafe, and you will find it won't even compile without some sort of null check:
foo.run { this?.subString(1) }
// or
foo?.run { subString(1) }
This is because the top-level function run accept anything Any & Any?. so an extension function with Null Receiver doesn't checked by Kotlin in runtime.
// v--- accept anything
public inline fun <T, R> T.run(block: T.() -> R): R = block()
Indeed, the inline function run is generated by Kotlin without any assertions if the receiver can be nullable, so it is more like a noinline function generated to Java code as below:
public static Object run(Object receiver, Function1<Object, Object> block){
//v--- the parameters checking is taken away if the reciever can be nullable
//Intrinsics.checkParameterIsNotNull(receiver, "receiver");
Intrinsics.checkParameterIsNotNull(block, "block");
// ^--- checking the `block` parameter since it can't be null
}
IF you want to call it in a safety way, you can use safe-call operator ?. instead, for example:
val foo: String? = null
// v--- short-circuited if the foo is null
foo?.run { println("foo") }
Is this possible if I do a null check before passing? For example:
fun main(args: Array<String>) {
var num: Int? = null
// Stuff happens that might make num not null
...
if (num != null) doSomething(num)
}
fun doSomething(number: Int) {
...
}
I don't understand why the compiler won't allow me to pass a nullable even though I check that it's not null first. Can anyone explain?
NOTE: starting from compiler version 1.0 beta the code in question works as is
The compiler can tell if the variable is mutated between check and use, at least in case of local variables like in this question, and in some other cases. See Jayson's answer for details.
http://kotlinlang.org/docs/reference/null-safety.html#checking-for-null-keyword--in-conditions says
The compiler tracks the information about the [null] check ... this only works where b is immutable (i.e. a local val or a member val which has a backing field and is not overridable), because otherwise it might happen that b changes to null after the check.
So something like this should work:
fun main(args: Array<String>) {
var num: Int? = null
// Stuff happens that might make num not null
...
val numVal: Int? = num
if (numVal != null) doSomething(numVal)
}
fun doSomething(number: Int) {
...
}
Of course, it would be nicer to rewrite "stuff happens" in such a way that you could make num into a val in the first place.
In current Kotlin (1.0 beta or newer) you do not have this issue anymore. Your code would compile. A local variable that is val or var can safely Smart Cast since the compiler can determine if the value could have mutated or not (on another thread for example).
Here is an excerpt from another Stack Overflow question that covers more aspects of nullability and Kotlin's operators for dealing with them.
More about null Checking and Smart Casts
If you protect access to a nullable type with a null check, the compiler will smart cast the value within the body of the statement to be non nullable. There are some complicated flows where this cannot happen, but for common cases works fine.
val possibleXyz: Xyz? = ...
if (possibleXyz != null) {
// allowed to reference members:
possiblyXyz.foo()
// or also assign as non-nullable type:
val surelyXyz: Xyz = possibleXyz
}
Or if you do a is check for a non nullable type:
if (possibleXyz is Xyz) {
// allowed to reference members:
possiblyXyz.foo()
}
And the same for 'when' expressions that also safe cast:
when (possibleXyz) {
null -> doSomething()
else -> possibleXyz.foo()
}
// or
when (possibleXyz) {
is Xyz -> possibleXyz.foo()
is Alpha -> possibleXyz.dominate()
is Fish -> possibleXyz.swim()
}
Some things do not allow the null check to smart cast for the later use of the variable. The example above uses a local variable that in no way could have mutated in the flow of the application, whether val or var this variable had no opportunity to mutate into a null. But, in other cases where the compiler cannot guarantee the flow analysis, this would be an error:
var nullableInt: Int? = ...
public fun foo() {
if (nullableInt != null) {
// Error: "Smart cast to 'kotlin.Int' is impossible, because 'nullableInt' is a mutable property that could have been changed by this time"
val nonNullableInt: Int = nullableInt
}
}
The lifecycle of the variable nullableInt is not completely visible and may be assigned from other threads, the null check cannot be smart cast into a non nullable value. See the "Safe Calls" topic below for a workaround.
Another case that cannot be trusted by a smart cast to not mutate is a val property on an object that has a custom getter. In this case the compiler has no visibility into what mutates the value and therefore you will get an error message:
class MyThing {
val possibleXyz: Xyz?
get() { ... }
}
// now when referencing this class...
val thing = MyThing()
if (thing.possibleXyz != null) {
// error: "Kotlin: Smart cast to 'kotlin.Int' is impossible, because 'p.x' is a property that has open or custom getter"
thing.possiblyXyz.foo()
}
read more: Checking for null in conditions
You can use let to simplify the code. The kotlin scope function introduces a local variable in the context of "num". No need to declare temporary variable numVal.
fun main(args: Array<String>) {
var num: Int? = null
// Stuff happens that might make num not null
...
num?.let{
doSomething(it)
}
}
Which works same as below but simpler and cleaner.
fun main(args: Array<String>) {
var num: Int? = null
// Stuff happens that might make num not null
...
val numVal: Int? = num
if (numVal != null) doSomething(numVal)
}
Use can use Scoping function let or apply along with null safe operator ?.
fragmentManager?.let{
viewPager.adapter = TasksPagerAdapter(it)
}
This way you can pass a nullable type to a non-nullable type parameter