Skip to content

Transient lambdas capture wrong parameters #2492

Open
@adrian-shape

Description

@adrian-shape

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions