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
Список данных не отображается в представлении Recycler в основном действии в приложении Android, используя kotlin для разработки. Как загрузить фрагмент в BottomNavigationView в зависимости от выбранного элемента? Как определить, является ли объект унаследованным от определенного класса в Котлине? Как использовать Kotlin, когда найти, является ли строка числовой? TornadoFX: разрешить копирование элемента из списка в буфер обмена Создание WAV-файла с помощью Okio Недвижимость без геттера в Котлине Объединение обязательных и произвольных необязательных аргументов конструктора с Groovy Котлин. привязка не обновление данных Почему не используется Intellij Idea Console для пользовательского ввода Использование функциональных интерфейсов с функциями функций в Котлине Улучшение парсинга Java / Kotlin JSON Android Studio и Kotlin: нерешенные ссылки: также Как показать только день и месяц в диалоговом окне выбора даты в Kotlin (Android)? Классы данных Kotlin содержат открытые функции