Correctly implement specialized MutableEntrySet.contains KT-41278

This is a workaround for the problem KT-43321.

Introduce an intermediate abstract set specialized for Map.Entry elements
and implement 'contains(Map.Entry)' method there.

Then inherit that intermediate set in entrysets of JS HashMap,
JS LinkedHashMap, JVM MapBuilder, that are specialized for
MutableMap.MutableEntry elements, so that no override of 'contains' is
required anymore.

This allows to avoid incorrect special 'contains' bridge being generated
that otherwise rejects all arguments except ones of MutableEntry type.
This commit is contained in:
Ilya Gorbunov
2020-11-12 05:10:29 +03:00
parent 0a3f3bef51
commit 28168bf230
5 changed files with 61 additions and 10 deletions
@@ -46,6 +46,12 @@ public actual abstract class AbstractMutableMap<K, V> protected actual construct
}
// intermediate abstract class to workaround KT-43321
internal abstract class AbstractEntrySet<E : Map.Entry<K, V>, K, V> : AbstractMutableSet<E>() {
final override fun contains(element: E): Boolean = containsEntry(element)
abstract fun containsEntry(element: Map.Entry<K, V>): Boolean
}
actual override fun clear() {
entries.clear()
}
@@ -1,7 +1,8 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
/*
* Based on GWT AbstractHashMap
* Copyright 2008 Google Inc.
@@ -20,14 +21,14 @@ import kotlin.collections.MutableMap.MutableEntry
// have to make sure mutating methods check `checkIsMutable`.
public actual open class HashMap<K, V> : AbstractMutableMap<K, V>, MutableMap<K, V> {
private inner class EntrySet : AbstractMutableSet<MutableEntry<K, V>>() {
private inner class EntrySet : AbstractEntrySet<MutableEntry<K, V>, K, V>() {
override fun add(element: MutableEntry<K, V>): Boolean = throw UnsupportedOperationException("Add is not supported on entries")
override fun clear() {
this@HashMap.clear()
}
override operator fun contains(element: MutableEntry<K, V>): Boolean = containsEntry(element)
override fun containsEntry(element: Map.Entry<K, V>): Boolean = this@HashMap.containsEntry(element)
override operator fun iterator(): MutableIterator<MutableEntry<K, V>> = internalMap.iterator()
@@ -121,4 +122,4 @@ public actual open class HashMap<K, V> : AbstractMutableMap<K, V>, MutableMap<K,
*/
public fun <V> stringMapOf(vararg pairs: Pair<String, V>): HashMap<String, V> {
return HashMap<String, V>(InternalStringMap(EqualityComparator.HashCode)).apply { putAll(pairs) }
}
}
@@ -1,7 +1,8 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
/*
* Based on GWT LinkedHashMap
* Copyright 2008 Google Inc.
@@ -40,7 +41,7 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
}
}
private inner class EntrySet : AbstractMutableSet<MutableEntry<K, V>>() {
private inner class EntrySet : AbstractEntrySet<MutableEntry<K, V>, K, V>() {
private inner class EntryIterator : MutableIterator<MutableEntry<K, V>> {
// The last entry that was returned from this iterator.
@@ -85,7 +86,7 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
this@LinkedHashMap.clear()
}
override operator fun contains(element: MutableEntry<K, V>): Boolean = containsEntry(element)
override fun containsEntry(element: Map.Entry<K, V>): Boolean = this@LinkedHashMap.containsEntry(element)
override operator fun iterator(): MutableIterator<MutableEntry<K, V>> = EntryIterator()
@@ -275,4 +276,4 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
*/
public fun <V> linkedStringMapOf(vararg pairs: Pair<String, V>): LinkedHashMap<String, V> {
return LinkedHashMap<String, V>(stringMapOf<Any>()).apply { putAll(pairs) }
}
}