Inline Class with "map" delegate

I seem to have stumbled over an issue using inline classes to represent values in a delegate backing map. such fields don’t appear to be “dereferenceable”. Any help appreciated.
Kotlin 1.3.31
JDK 1.8.0_212 (AdoptOpenJDK)

package com.example.error

inline class FieldValue(val value: String)

class TestError {
    enum class RequestFields {
        ENUM_ONE
    }

    private data class RequestInputParameters(
            private val backingMap: Map<RequestFields, FieldValue>
    ) : Map<RequestFields, FieldValue> by backingMap

    companion object {
        @JvmStatic
        fun main(args: Array<String>) {

            val testMap = mapOf(RequestFields.ENUM_ONE to FieldValue("value1")
            )
            val test = testMap[RequestFields.ENUM_ONE] // works!
            println(test)

            val testMap2 = RequestInputParameters(
                    mapOf(RequestFields.ENUM_ONE to FieldValue("value1"))
            )
            val test2 = testMap2[RequestFields.ENUM_ONE] // does not work :-(
            println(test2)

        }
    }
}

Here is a runnable version:

inline class FieldValue(val value: String)

enum class RequestFields {
    ENUM_ONE
}

private data class RequestInputParameters(
    private val backingMap: Map<RequestFields, FieldValue>
) : Map<RequestFields, FieldValue> by backingMap

fun main() {
    val testMap = mapOf(RequestFields.ENUM_ONE to FieldValue("value1"))
    val test = testMap[RequestFields.ENUM_ONE] // works!
    println(test)

    val testMap2 = RequestInputParameters(mapOf(RequestFields.ENUM_ONE to FieldValue("value1")))
    val test2 = testMap2[RequestFields.ENUM_ONE] // does not work :-(
    println(test2)
}

I also took a look at the generate bytecode. It contains this (decompiled to Java) code:

final class RequestInputParameters implements Map, KMappedMarker
   @Nullable
   public String get(@NotNull RequestFields key) {
      Intrinsics.checkParameterIsNotNull(key, "key");
      return (String)this.backingMap.get(key);
   }
}

Normally, when a type parameter is instantiated with an inline class, the boxed version is used instead. However, in this case, the unboxed version is used. This definitely looks like a compiler bug to me.

3 Likes

I created an issue: https://youtrack.jetbrains.com/issue/KT-31585

1 Like