NPE for reflection field in 1.5

Hello. I’m developing android app and I’ve met weird NPE since I migrate from 1.4.30 → 1.5.21.
It seems like a?.b is treated as non-null in 1.5.21.
(java-decompiled code is same for 1.4.30, 1.5.21)

What’s happening here?

class A(
    val b: B
)
class B(
    val c: String
)
fun createByReflection(): A? = A(B("aaa")).apply {
    val field = javaClass.declaredFields.find { it.name == "b" }!!
    field.isAccessible = true
    field.set(this, null)
}
fun main() {
    val a = createByReflection()
    println(a?.b) // this outputs null of course.
    println(a?.b?.c) // In 1.5.21, this throws java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String B.getC()' on a null object reference
}

Seems reasonable, b is non-null in A. Yet you’re hacking around with reflection to change that.
The compiler is very reasonable here in assuming b is not null.

Yes it’s understandable. but
was there release note about this change?

2021년 10월 5일 (화) 오후 5:52, Alberto Arri via Kotlin Discussions <kotlinlang@discoursemail.com>님이 작성:

If your code rely on an undefined behaviour (which your code very much is) , you are on your own. the Kotlin team probably don’t have test for that case and won’t add one, thus the lack of changelog for that.

If it is ‘undefined behavior’ then I agree that it doesn’t have to be in release note.
but I still wish there was a note or something.
(I used reflection directly in my example, but it was Gson in the production code.)

Ah, I see, that is unfortunate. If it is possible I would advise you to migrate to kotlinx.serialization, it’s reflection-free, written in kotlin, maintained by JetBrains and works a treat :slight_smile:

Thank you. I’ll try kotlinx.serialization.

Thank you, reported https://youtrack.jetbrains.com/issue/KT-49136

Ohh, I’m actually surprised this went to YouTrack. Why is it considered a bug? I guess the generated bytecode should not check not-null variables for nulls. Or maybe we assume that ?. operator should enforce such check, even if used on a not-null?

Interesting. So this is not intentional change?
Moreover, in KT-49136, it is not reproduced in 1.6…
I’ll see how it goes.