Add Map.getOrDefault method as PlatformDependent declaration with refined signature

- First parameter should have type of K instead of Any
- Special bridge should return second parameter if a key has wrong type
- Special bridge may throw an exception if defaultValue has wrong type

 #KT-13209 Fixed
This commit is contained in:
Denis Zharkov
2016-07-27 12:14:08 +03:00
parent 169acf2f31
commit 915e36cb02
15 changed files with 353 additions and 26 deletions
@@ -0,0 +1,66 @@
// FULL_JDK
// WITH_RUNTIME
class A : MutableMap<Any, Any?> {
override val entries: MutableSet<MutableMap.MutableEntry<Any, Any?>>
get() = throw UnsupportedOperationException()
override val keys: MutableSet<Any>
get() = throw UnsupportedOperationException()
override val values: MutableCollection<Any?>
get() = throw UnsupportedOperationException()
override fun clear() {
throw UnsupportedOperationException()
}
override fun put(key: Any, value: Any?): Any? {
throw UnsupportedOperationException()
}
override fun putAll(from: Map<out Any, Any?>) {
throw UnsupportedOperationException()
}
override fun remove(key: Any): Any? {
throw UnsupportedOperationException()
}
override val size: Int
get() = throw UnsupportedOperationException()
override fun containsKey(key: Any): Boolean {
throw UnsupportedOperationException()
}
override fun containsValue(value: Any?): Boolean {
throw UnsupportedOperationException()
}
override fun get(key: Any): Any? {
throw UnsupportedOperationException()
}
override fun isEmpty(): Boolean {
throw UnsupportedOperationException()
}
override fun getOrDefault(key: Any, defaultValue: Any?): Any? {
if (key == "abc") return "cde"
return defaultValue
}
}
fun box(): String {
val a = A()
if (a.getOrDefault("abc", "xyz") != "cde") return "fail 1"
if (a.getOrDefault("56", "123") != "123") return "fail 2"
val mm = a as MutableMap<Any?, Any?>
if (mm.getOrDefault("abc", "xyz") != "cde") return "fail 3"
if (mm.getOrDefault("56", 123) != 123) return "fail 4"
if (mm.getOrDefault(1, "456") != "456") return "fail 5"
if (mm.getOrDefault(null, "qwe") != "qwe") return "fail 6"
if (mm.getOrDefault("abc", null) != "cde") return "fail 7"
return "OK"
}
@@ -0,0 +1,74 @@
// FULL_JDK
// WITH_RUNTIME
class A : MutableMap<String, String> {
override val entries: MutableSet<MutableMap.MutableEntry<String, String>>
get() = throw UnsupportedOperationException()
override val keys: MutableSet<String>
get() = throw UnsupportedOperationException()
override val values: MutableCollection<String>
get() = throw UnsupportedOperationException()
override fun clear() {
throw UnsupportedOperationException()
}
override fun put(key: String, value: String): String? {
throw UnsupportedOperationException()
}
override fun putAll(from: Map<out String, String>) {
throw UnsupportedOperationException()
}
override fun remove(key: String): String? {
throw UnsupportedOperationException()
}
override val size: Int
get() = throw UnsupportedOperationException()
override fun containsKey(key: String): Boolean {
throw UnsupportedOperationException()
}
override fun containsValue(value: String): Boolean {
throw UnsupportedOperationException()
}
override fun get(key: String): String? {
throw UnsupportedOperationException()
}
override fun isEmpty(): Boolean {
throw UnsupportedOperationException()
}
override fun getOrDefault(key: String, defaultValue: String): String {
if (key == "abc") return "cde"
return defaultValue
}
}
fun box(): String {
val a = A()
if (a.getOrDefault("abc", "xyz") != "cde") return "fail 1"
if (a.getOrDefault("56", "123") != "123") return "fail 2"
val mm = a as MutableMap<Any?, Any?>
if (mm.getOrDefault("abc", "xyz") != "cde") return "fail 3"
if (mm.getOrDefault("56", "123") != "123") return "fail 4"
if (mm.getOrDefault(1, "456") != "456") return "fail 5"
if (mm.getOrDefault(null, "qwe") != "qwe") return "fail 6"
try {
// This is a known problem, there's no way to implement type-safe bridge/barrier properly:
// 'override fun getOrDefault(key: String, defaultValue: String): String' expects two strings,
// and returning defaultValue if Int was received seems incorrect here
mm.getOrDefault("abc", 123)
return "fail 7"
} catch (e: java.lang.ClassCastException) {
}
return "OK"
}
@@ -0,0 +1,80 @@
// FULL_JDK
// WITH_RUNTIME
class A : MutableMap<Any, Any> {
override val entries: MutableSet<MutableMap.MutableEntry<Any, Any>>
get() = throw UnsupportedOperationException()
override val keys: MutableSet<Any>
get() = throw UnsupportedOperationException()
override val values: MutableCollection<Any>
get() = throw UnsupportedOperationException()
override fun clear() {
throw UnsupportedOperationException()
}
override fun put(key: Any, value: Any): Any? {
throw UnsupportedOperationException()
}
override fun putAll(from: Map<out Any, Any>) {
throw UnsupportedOperationException()
}
override fun remove(key: Any): Any? {
throw UnsupportedOperationException()
}
override val size: Int
get() = throw UnsupportedOperationException()
override fun containsKey(key: Any): Boolean {
throw UnsupportedOperationException()
}
override fun containsValue(value: Any): Boolean {
throw UnsupportedOperationException()
}
override fun get(key: Any): Any? {
throw UnsupportedOperationException()
}
override fun isEmpty(): Boolean {
throw UnsupportedOperationException()
}
override fun getOrDefault(key: Any, defaultValue: Any): Any {
// this condition can not be true because of checkParameterIsNotNull checks in the begin of every method, but it's left here
// to emphasize that we expect these parameters are not null
if (key == null || defaultValue == null) {
throw IllegalArgumentException("fail")
}
if (key == "abc") return "cde"
return defaultValue
}
}
fun box(): String {
val a = A()
if (a.getOrDefault("abc", "xyz") != "cde") return "fail 1"
if (a.getOrDefault("56", "123") != "123") return "fail 2"
val mm = a as MutableMap<Any?, Any?>
if (mm.getOrDefault("abc", "xyz") != "cde") return "fail 3"
if (mm.getOrDefault("56", 123) != 123) return "fail 4"
if (mm.getOrDefault(1, "456") != "456") return "fail 5"
if (mm.getOrDefault(null, "qwe") != "qwe") return "fail 6"
try {
// This is a known problem, there's no way to implement type-safe bridge/barrier properly:
// 'override fun getOrDefault(key: Any, defaultValue: Any): Any' expects two not-nullable values,
// and returning defaultValue if null was received seems incorrect here
mm.getOrDefault("abc", null)
return "fail 7"
} catch (e: java.lang.IllegalArgumentException) {
// Parameter specified as non-null is null
}
return "OK"
}