Kotlin cannot resolve non-nullability - kotlin

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?

Related

Kotlin smart cast fails but only with operator function

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

Kotlin smart cast not working with extensions functions

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

How to overload functions with same param types but one is nullable

I'm trying to add two extension function to Calendar Class in Android to convert the specific date-time pattern to Calendar and vise versa
fun Calendar.fromIsoString(date: String): Calendar = this.apply {
time = SimpleDateFormat(SERVER_DATE_PATTERN, Locale.US).parse(date)
}
fun Calendar.fromIsoString(date: String?): Calendar? {
if (date == null) return null
time = SimpleDateFormat(SERVER_DATE_PATTERN, Locale.US).parse(date)
return this
}
But it gives me the following Error:
Platform declaration clash: The following declarations have the same JVM signature (fromIsoString(Ljava/util/Calendar;Ljava/lang/String;)Ljava/util/Calendar;)
Is it possible to have these two functions besides each other? how?
Note:
I somehow handled the problem by adding a Unit optional parameter to one of the functions:
fun Calendar.fromIsoString(date: String?, a: Unit = Unit): Calendar? {
if (date == null) return null
time = SimpleDateFormat(SERVER_DATE_PATTERN, Locale.US).parse(date)
return this
}
But I think it is tricky and not a good practice!
Is there any better solution?
There is a simple solution that allows you to do this without changing your methods or the name you want to call them from Kotlin.
For Kotlin the distinction between the two methods is clear, but for the JVM it is not. Therefore, just tell Kotlin that you want a different internal JVM name for one of the methods which will not impact Kotlin code at all. Only Java code would see the alternative name. For example:
fun Calendar.fromIsoString(date: String): Calendar = this.apply {
// ... your code without change
}
#JvmName("fromIsoStringNullable") // <-- this solves your problem without changing the name in Kotlin
fun Calendar.fromIsoString(date: String?): Calendar? {
// ... your code without change
}
voilĂ ! no more error! You can call either version from Kotlin using the same name someCalendar.fromIsoString(...)
Other answers and comments suggesting the nullability is syntactical sugar are far from correct. These types are written into the bytecode as extra metadata that only Kotlin will see and enforce. But on top of that, it also adds a #Nullable annotation to the parameter. In fact, all Kotlin generated function parameters have #NotNull and #Nullable annotations in the bytecode for other languages or analyzers to see and enforce if they care enough to do so.

What is the purpose of having bound class reference return a covariant type?

I'm playing with reflection and I came out with this problem. When using bound class reference via the ::class syntax, I get a covariant KClass type:
fun <T> foo(entry: T) {
with(entry::class) {
this // is instance of KClass<out T>
}
}
As I could learn from the docs, this will return the exact type of the object, in case it is instance of a subtype of T, hence the variance modifier.
However this prevents retrieving properties declared in the T class and getting their value (which is what I'm trying to do)
fun <T> foo(entry: T) {
with(entry::class) {
for (prop in memberProperties) {
val v = prop.get(entry) //compile error: I can't consume T
}
}
}
I found that a solution is using javaClass.kotlin extension function on the object reference, to get instead the invariant type:
fun <T> foo(entry: T) {
with(entry.javaClass.kotlin) {
this // is instance of KClass<T>
}
}
This way, I get both the exact type at runtime and the possibility to consume the type.
Interestingly, if I use a supertype instead of a generic, with the latter method I still get access to the correct type, without the need of variance:
class Derived: Base()
fun foo(entry: Base) {
with(entry.javaClass.kotlin) {
println(this == Derived::class)
}
}
fun main(args: Array<String>) {
val derived = Derived()
foo(derived) // prints 'true'
}
If I got it correct, ::class is equal to calling the java getClass, which returns a variant type with a wildcard, while javaClass is a getClass with a cast to the specific type.
Still, I don't get why would I ever need a covariant KClass, when it limits me to only produce the type, given that there are other ways to access the exact class at runtime and use it freely, and I wonder if the more immediate ::class should return an invariant type by design.
The reason for covariance in bound ::class references is, the actual runtime type of an object the expression is evaluated to might differ from the declared or inferred type of the expression.
Example:
open class Base
class Derived : Base()
fun someBase(): Base = Derived()
val kClass = someBase()::class
The expression someBase() is typed as Base, but at runtime it's a Derived object that it gets evaluated to.
Typing someBase()::class as invariant KClass<Base> is simply incorrect, in fact, the actuall result of evaluating this expression is KClass<Derived>.
To solve this possible inconsistency (that would lead to broken type-safety), all bound class references are covariant: someBase()::class is KClass<out Base>, meaning that at runtime someBase() might be a subtype of Base, and therefore this might be a class token of a subtype of Base.
This is, of course, not the case with unbound class references: when you take Base::class, you know for sure that it's the class token of Base and not of some of its subtypes, so it's invariant KClass<Base>.

Why do unsafe .run() call works fine on a null value in Kotlin?

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") }