2017-12-08 42 views
7

के लिए मैं इस वर्ग में परिभाषित किया गया है: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) 

हो रहा क्यों है?

संपादित करें:

decompiled कोड में थोड़ा खुदाई दोनों को पूरी तरह से अलग कोड का संकलन किया मिलता है।

काम कर संस्करण में += बिना यह करने के लिए संकलित हो जाता है:

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

गैर कार्यरत वर्शन पर संकलित हो जाता है: https://github.com/JetBrains/kotlin/blob/1.2.0/libraries/stdlib/src/kotlin/collections/Maps.kt#L175

मैं:

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

तो यह इस समारोह calles अभी भी कोई जानकारी नहीं है कि यह त्रुटि क्यों उत्पन्न करता है, सिर्फ पहला संस्करण अलग-अलग व्यवहार क्यों करता है।

संपादित करें: YouTrack link to the report

उत्तर

4

संपादित करें: हाँ, यह एक बग, यह KT-14227 साथ विलय कर दिया गया है: जब plusAssign ऑपरेटर


साथ MutableMap.set का उपयोग कर

गलत कोड जनरेट किया गया है

संकलन के बाद (या इस मामले में अपघटन), 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 is indeed the reason for the method being private बताया।

@InlineOnly निर्दिष्ट करता है कि विधि सीधे कभी नहीं बुलाया जाना चाहिए:

इनलाइन करने के बिना

निर्दिष्ट करता है कि इस समारोह सीधे नहीं बुलाया जाना चाहिए ताकि मुझे लगता है कि यह एक मामला है जहां के लिए कॉल set को रेखांकित किया जाना चाहिए, लेकिन यह नहीं था।

कॉल को रेखांकित किया गया था, तो आप कामकाजी संस्करण के साथ व्यावहारिक रूप से समान संकलित कोड के साथ समाप्त हो गए थे, क्योंकि विधि में केवल put पर कॉल है।

मुझे संदेह है कि यह एक कंपाइलर बग के कारण है।

+0

हू, दिलचस्प। तो मुझे शायद कोटलिन कंपाइलर में एक बग मिला? – usbpc102

+0

@ usbpc102 ऐसा लगता है जैसे आपके पास है, हालांकि यह अजीब लगता है कि यह – Moira

+0

होगा, मैंने अभी जांच की है और आपकी धारणा [यह निजी क्यों है सही है] (https://stackoverflow.com/questions/45763075/what-is- इनलाइनलाइन-एनोटेशन) – usbpc102