Kotlin IllegalAccessError с + = и – = для делегированного интерфейса

Я определил этот класс:

class NeverNullMap<K, V>(private val backing: MutableMap<K, V> = mutableMapOf(), val default: () -> V): MutableMap<K, V> by backing { override operator fun get(key: K): V = backing.getOrPut(key, default) } 

И я могу использовать его совершенно прекрасно:

 fun main(args: Array<String>) { val myMap = NeverNullMap<String, Int> {0} println(myMap["test"]) myMap["test"] = myMap["test"] + 10 println(myMap["test"]) } 

как и ожидалось, выход:

 0 10 

Но когда я пытаюсь изменить его на:

 fun main(args: Array<String>) { val myMap = NeverNullMap<String, Int> {0} println(myMap["test"]) myMap["test"] += 10 println(myMap["test"]) } 

Я получил:

 Exception in thread "main" java.lang.IllegalAccessError: tried to access method kotlin.collections.MapsKt__MapsKt.set(Ljava/util/Map;Ljava/lang/Object;Ljava/lang/Object;)V from class Day08Kt at Day08Kt.main(Day08.kt:10) 

Почему это происходит?

Редактировать:

Копая бит в декомпилированный код, оба скомпилируются до совершенно разного кода.

В рабочей версии без += она компилируется в:

  Map var2 = (Map)myMap; String var3 = "test"; Integer var4 = ((Number)myMap.get("test")).intValue() + 10; var2.put(var3, var4); 

Нерабочая версия скомпилирована для:

 MapsKt.set(myMap, "test", ((Number)myMap.get("test")).intValue() + 10); 

Поэтому он вызывает эту функцию: https://github.com/JetBrains/kotlin/blob/1.2.0/libraries/stdlib/src/kotlin/collections/Maps.kt#L175

Я до сих пор не знаю, почему это вызывает ошибку, просто почему первая версия ведет себя по-разному.

Изменить: ссылка YouTrack на отчет

Изменить: да, это ошибка, она была объединена с KT-14227 :

Неправильный код генерируется при использовании MutableMap.set с plusAssign оператора plusAssign


После компиляции (или декомпиляции в этом случае) MapsKt.set превращается в private метод:

 @InlineOnly private static final void set(@NotNull Map $receiver, Object key, Object value) { Intrinsics.checkParameterIsNotNull($receiver, "$receiver"); $receiver.put(key, value); } 

Это объясняет IllegalAccessError .

Теперь о том, почему он частный, я только размышляю, но я чувствую, что это может быть из-за этого:

@ usbpc102 указал, что @InlineOnly действительно является причиной того, что метод является private .

@InlineOnly указывает, что метод никогда не должен вызываться напрямую:

Указывает, что эту функцию нельзя вызывать напрямую без вставки

поэтому я чувствую, что это случай, когда вызов set должен быть встроен, но это не так.

Если бы вызов был встроен, вы бы закончили с компилированным кодом, который практически идентичен рабочей версии, так как метод содержит только вызов.

Я подозреваю, что это связано с ошибкой компилятора.

Intereting Posts
Можем ли мы достичь безопасности типа компиляции для объединения типов, которые мы не можем контролировать? Cloud.orbit.exception.UncheckedException: не знаю, как обрабатывать состояние Kotlin: инкрементальная компиляция с Gradle Эллипсис-оператор эквивалентности Java в Котлине Kotlin Bytecode – Как анализировать в IntelliJ IDEA? Разумные ситуации для использования `Let` Котлина Kotlin, Mockito и Android Test Instrumentation. Свойство Lateinit не было инициализировано Ввод / вывод дженериков для абстрактного контейнерного инструмента в Котлине? Kotlin Constructor Crash Нужно ли использовать @Repository, когда я использую только JdbcTemplate в своем классе DAO? Какова основная разница между сбросом и сокращением в Котлине? Когда использовать какой? запустить Android-версию 2.3.3 проект kotlin в android studio 3.0.1 после обновления BigInteger в Котлине Kotlin Generics: Котлин не признает мой класс с правильным наследованием Andoird anko DSL – добавление текстовых просмотров и создание их «новой строки», когда нет больше ширины экрана?