Delegates should perform null-check when accessed


#1

Kotlin property delegates do not infer types based on the property they’re associated with. For example:

import java.util.Scanner

fun methodThatReturnsAPlatformType() = Scanner("").findInLine("") // Returns type String!

fun main(args: Array<String>) {
//sampleStart
  val property: String by lazy { methodThatReturnsAPlatformType() } // Returns Lazy<String!>
  println(property) // Should throw IllegalStateException if `property` value is null
//sampleEnd
}

Now if we simply assigned the property instead of a Lazy delegate, we get the correct error:

import java.util.Scanner

fun methodThatReturnsAPlatformType() = Scanner("").findInLine("") // Returns type String!

fun main(args: Array<String>) {
//sampleStart
  val property: String = methodThatReturnsAPlatformType() // Returns String!
  println(property)
//sampleEnd
}

To work around this issue, we can explicitly set the type param for the delegate, val property = lazy<String>.

This StackOverflow question shows a case where @kolossal ran into this issue.

I believe this should be changed so that delegates returning a platform type should have an extra null check. All other cases where a non-nullable property is assigned a null value throws an error, so should delegates.

This example is in direct opposition to this paragraph from the Kotlin docs (https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types):

If we choose a non-null type, the compiler will emit an assertion upon assignment. This prevents Kotlin’s non-null variables from holding nulls. Assertions are also emitted when we pass platform values to Kotlin functions expecting non-null values etc. Overall, the compiler does its best to prevent nulls from propagating far through the program (although sometimes this is impossible to eliminate entirely, because of generics).


#2

This case is covered by the issue https://youtrack.jetbrains.com/issue/KT-8135