Open
Description
Describe the bug
When you have a @Serializable
class with a @Transient
lambda, the lambda captures the wrong parameters. The code compiles just fine, but crashes during runtime.
To Reproduce
If we have the following class, and call StringWrapper("1.0").double
data class DoubleWrapper(val value: Double)
interface DoubleWrapperBuilder {
fun build(value: Double): DoubleWrapper = DoubleWrapper(value)
}
@Serializable
data class StringWrapper(
val value: String,
@Transient val doubleWrapperBuilder: DoubleWrapperBuilder = object : DoubleWrapperBuilder {
override fun build(value: Double): DoubleWrapper = DoubleWrapper(value)
}
) {
val double: DoubleWrapper
get() {
val doubleValue: Double = value.toDouble()
Timber.d("Value as double: $doubleValue")
return doubleWrapperBuilder.build(doubleValue)
}
}
Then this is the result:
Value as double: 1.0
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.example.foo.StringWrapper.getValue()' on a null object reference
at com.example.foo.StringWrapper$2.build(Foo.kt:36)
at com.example.foo.StringWrapper.getDouble(Foo.kt:46)
If I remove the annotations, the code behaves as expected.
If I change the argument names inside DoubleWrapperBuilder to not clash, then the code behaves as expected.
I have also in some other iteration of this bug with different usage gotten a ClassCastException from String to Number while having Java code involved.
Expected behavior
Calling the .double function as specified should not crash.
Environment
- Kotlin version: 1.9.10
- Library version: 1.6.0
- Kotlin platforms: JVM / Android
- Gradle version: 8.3