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:
@@ -937,13 +937,19 @@ public class FunctionCodegen {
|
||||
@NotNull Type returnType,
|
||||
@Nullable Type[] delegateParameterTypes
|
||||
) {
|
||||
BuiltinMethodsWithSpecialGenericSignature.DefaultValue defaultValue =
|
||||
BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription typeSafeBarrierDescription =
|
||||
BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor);
|
||||
if (defaultValue == null) return;
|
||||
if (typeSafeBarrierDescription == null) return;
|
||||
|
||||
FunctionDescriptor overriddenBuiltin =
|
||||
BuiltinMethodsWithSpecialGenericSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(descriptor);
|
||||
|
||||
assert overriddenBuiltin != null : "Overridden built-in method should not be null for " + descriptor;
|
||||
|
||||
Label defaultBranch = new Label();
|
||||
|
||||
for (int i = 0; i < descriptor.getValueParameters().size(); i++) {
|
||||
if (!typeSafeBarrierDescription.checkParameter(i)) continue;
|
||||
boolean isCheckForAny = delegateParameterTypes == null || OBJECT_TYPE.equals(delegateParameterTypes[i]);
|
||||
|
||||
KotlinType kotlinType = descriptor.getValueParameters().get(i).getType();
|
||||
@@ -967,7 +973,13 @@ public class FunctionCodegen {
|
||||
iv.goTo(afterDefaultBranch);
|
||||
|
||||
iv.visitLabel(defaultBranch);
|
||||
StackValue.constant(defaultValue.getValue(), returnType).put(returnType, iv);
|
||||
|
||||
if (typeSafeBarrierDescription.equals(BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT)) {
|
||||
iv.load(2, returnType);
|
||||
}
|
||||
else {
|
||||
StackValue.constant(typeSafeBarrierDescription.getDefaultValue(), returnType).put(returnType, iv);
|
||||
}
|
||||
iv.areturn(returnType);
|
||||
|
||||
iv.visitLabel(afterDefaultBranch);
|
||||
|
||||
@@ -103,6 +103,7 @@ public interface Map</*0*/ K, /*1*/ out V> {
|
||||
public abstract fun containsKey(/*0*/ key: K): kotlin.Boolean
|
||||
public abstract fun containsValue(/*0*/ value: @kotlin.UnsafeVariance() V): kotlin.Boolean
|
||||
public abstract operator fun get(/*0*/ key: K): V?
|
||||
@kotlin.internal.PlatformDependent() public open fun getOrDefault(/*0*/ key: K, /*1*/ defaultValue: @kotlin.UnsafeVariance() V): V
|
||||
public abstract fun isEmpty(): kotlin.Boolean
|
||||
|
||||
public interface Entry</*0*/ out K, /*1*/ out V> {
|
||||
@@ -188,6 +189,7 @@ public interface MutableMap</*0*/ K, /*1*/ V> : kotlin.collections.Map<K, V> {
|
||||
public abstract override /*1*/ /*fake_override*/ fun containsKey(/*0*/ key: K): kotlin.Boolean
|
||||
public abstract override /*1*/ /*fake_override*/ fun containsValue(/*0*/ value: V): kotlin.Boolean
|
||||
public abstract override /*1*/ /*fake_override*/ fun get(/*0*/ key: K): V?
|
||||
@kotlin.internal.PlatformDependent() public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ key: K, /*1*/ defaultValue: V): V
|
||||
public abstract override /*1*/ /*fake_override*/ fun isEmpty(): kotlin.Boolean
|
||||
public abstract fun put(/*0*/ key: K, /*1*/ value: V): V?
|
||||
public abstract fun putAll(/*0*/ from: kotlin.collections.Map<out K, V>): kotlin.Unit
|
||||
|
||||
@@ -123,7 +123,7 @@ public interface Map</*0*/ K, /*1*/ out V> {
|
||||
public abstract fun containsValue(/*0*/ value: @kotlin.UnsafeVariance() V): kotlin.Boolean
|
||||
public open fun forEach(/*0*/ p0: java.util.function.BiConsumer<in K!, in V!>!): kotlin.Unit
|
||||
public abstract operator fun get(/*0*/ key: K): V?
|
||||
public open fun getOrDefault(/*0*/ p0: kotlin.Any!, /*1*/ p1: @kotlin.UnsafeVariance() V!): V!
|
||||
@kotlin.internal.PlatformDependent() public open fun getOrDefault(/*0*/ key: K, /*1*/ defaultValue: @kotlin.UnsafeVariance() V): V
|
||||
public abstract fun isEmpty(): kotlin.Boolean
|
||||
|
||||
public interface Entry</*0*/ out K, /*1*/ out V> {
|
||||
@@ -229,7 +229,7 @@ public interface MutableMap</*0*/ K, /*1*/ V> : kotlin.collections.Map<K, V> {
|
||||
public abstract override /*1*/ /*fake_override*/ fun containsValue(/*0*/ value: V): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun forEach(/*0*/ p0: java.util.function.BiConsumer<in K!, in V!>!): kotlin.Unit
|
||||
public abstract override /*1*/ /*fake_override*/ fun get(/*0*/ key: K): V?
|
||||
public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ p0: kotlin.Any!, /*1*/ p1: V!): V!
|
||||
@kotlin.internal.PlatformDependent() public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ key: K, /*1*/ defaultValue: V): V
|
||||
public abstract override /*1*/ /*fake_override*/ fun isEmpty(): kotlin.Boolean
|
||||
public open fun merge(/*0*/ p0: K!, /*1*/ p1: V!, /*2*/ p2: java.util.function.BiFunction<in V!, in V!, out V!>!): V!
|
||||
public abstract fun put(/*0*/ key: K, /*1*/ value: V): V?
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
+80
@@ -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"
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
abstract class A : Map<Int, String>
|
||||
|
||||
fun foo(x: Map<Int, String>, a: A, b: java.util.HashMap<Int, String>) {
|
||||
x.getOrDefault(1, "")
|
||||
x.getOrDefault(<!TYPE_MISMATCH!>""<!>, "")
|
||||
x.getOrDefault(1, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!>)
|
||||
x.getOrDefault(<!TYPE_MISMATCH!>""<!>, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!>)
|
||||
|
||||
a.getOrDefault(1, "")
|
||||
a.getOrDefault(<!TYPE_MISMATCH!>""<!>, "")
|
||||
a.getOrDefault(1, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!>)
|
||||
a.getOrDefault(<!TYPE_MISMATCH!>""<!>, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!>)
|
||||
|
||||
b.getOrDefault(1, "")
|
||||
b.getOrDefault(<!TYPE_MISMATCH!>""<!>, "")
|
||||
b.getOrDefault(1, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!>)
|
||||
b.getOrDefault(<!TYPE_MISMATCH!>""<!>, <!CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!>)
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ x: kotlin.collections.Map<kotlin.Int, kotlin.String>, /*1*/ a: A, /*2*/ b: java.util.HashMap<kotlin.Int, kotlin.String>): kotlin.Unit
|
||||
|
||||
public abstract class A : kotlin.collections.Map<kotlin.Int, kotlin.String> {
|
||||
public constructor A()
|
||||
public abstract override /*1*/ /*fake_override*/ val entries: kotlin.collections.Set<kotlin.collections.Map.Entry<kotlin.Int, kotlin.String>>
|
||||
public abstract override /*1*/ /*fake_override*/ val keys: kotlin.collections.Set<kotlin.Int>
|
||||
public abstract override /*1*/ /*fake_override*/ val size: kotlin.Int
|
||||
public abstract override /*1*/ /*fake_override*/ val values: kotlin.collections.Collection<kotlin.String>
|
||||
public abstract override /*1*/ /*fake_override*/ fun containsKey(/*0*/ key: kotlin.Int): kotlin.Boolean
|
||||
public abstract override /*1*/ /*fake_override*/ fun containsValue(/*0*/ value: kotlin.String): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun forEach(/*0*/ p0: java.util.function.BiConsumer<in kotlin.Int!, in kotlin.String!>!): kotlin.Unit
|
||||
public abstract override /*1*/ /*fake_override*/ fun get(/*0*/ key: kotlin.Int): kotlin.String?
|
||||
@kotlin.internal.PlatformDependent() public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ key: kotlin.Int, /*1*/ defaultValue: kotlin.String): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public abstract override /*1*/ /*fake_override*/ fun isEmpty(): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+2
-2
@@ -20,7 +20,7 @@ public final class KotlinMap1</*0*/ K, /*1*/ V> : java.util.AbstractMap<K, V> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun forEach(/*0*/ p0: java.util.function.BiConsumer<in K!, in V!>!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun get(/*0*/ key: K!): V?
|
||||
public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ p0: kotlin.Any!, /*1*/ p1: V!): V!
|
||||
@kotlin.internal.PlatformDependent() public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ key: K!, /*1*/ defaultValue: V!): V!
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun isEmpty(): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun merge(/*0*/ p0: K!, /*1*/ p1: V!, /*2*/ p2: java.util.function.BiFunction<in V!, in V!, out V!>!): V!
|
||||
@@ -53,7 +53,7 @@ public final class KotlinMap2 : java.util.AbstractMap<kotlin.String, kotlin.Int>
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun forEach(/*0*/ p0: java.util.function.BiConsumer<in kotlin.String!, in kotlin.Int!>!): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun get(/*0*/ key: kotlin.String!): kotlin.Int?
|
||||
public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ p0: kotlin.Any!, /*1*/ p1: kotlin.Int!): kotlin.Int!
|
||||
@kotlin.internal.PlatformDependent() public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ key: kotlin.String!, /*1*/ defaultValue: kotlin.Int!): kotlin.Int!
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun isEmpty(): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun merge(/*0*/ p0: kotlin.String!, /*1*/ p1: kotlin.Int!, /*2*/ p2: java.util.function.BiFunction<in kotlin.Int!, in kotlin.Int!, out kotlin.Int!>!): kotlin.Int!
|
||||
|
||||
+3
-3
@@ -17,7 +17,7 @@ public open class MapRemove {
|
||||
public abstract override /*1*/ /*fake_override*/ fun containsValue(/*0*/ value: V!): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun forEach(/*0*/ p0: java.util.function.BiConsumer<in K!, in V!>!): kotlin.Unit
|
||||
public abstract override /*1*/ /*fake_override*/ fun get(/*0*/ key: K!): V?
|
||||
public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ p0: kotlin.Any!, /*1*/ p1: V!): V!
|
||||
@kotlin.internal.PlatformDependent() public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ key: K!, /*1*/ defaultValue: V!): V!
|
||||
public abstract override /*1*/ /*fake_override*/ fun isEmpty(): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun merge(/*0*/ p0: K!, /*1*/ p1: V!, /*2*/ p2: java.util.function.BiFunction<in V!, in V!, out V!>!): V!
|
||||
public abstract override /*1*/ /*fake_override*/ fun put(/*0*/ key: K!, /*1*/ value: V!): V?
|
||||
@@ -44,7 +44,7 @@ public open class MapRemove {
|
||||
public abstract override /*1*/ /*fake_override*/ fun containsValue(/*0*/ value: kotlin.Int!): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun forEach(/*0*/ p0: java.util.function.BiConsumer<in kotlin.String!, in kotlin.Int!>!): kotlin.Unit
|
||||
public abstract override /*1*/ /*fake_override*/ fun get(/*0*/ key: kotlin.String!): kotlin.Int?
|
||||
public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ p0: kotlin.Any!, /*1*/ p1: kotlin.Int!): kotlin.Int!
|
||||
@kotlin.internal.PlatformDependent() public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ key: kotlin.String!, /*1*/ defaultValue: kotlin.Int!): kotlin.Int!
|
||||
public abstract override /*1*/ /*fake_override*/ fun isEmpty(): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun merge(/*0*/ p0: kotlin.String!, /*1*/ p1: kotlin.Int!, /*2*/ p2: java.util.function.BiFunction<in kotlin.Int!, in kotlin.Int!, out kotlin.Int!>!): kotlin.Int!
|
||||
public abstract override /*1*/ /*fake_override*/ fun put(/*0*/ key: kotlin.String!, /*1*/ value: kotlin.Int!): kotlin.Int?
|
||||
@@ -71,7 +71,7 @@ public open class MapRemove {
|
||||
public abstract override /*1*/ /*fake_override*/ fun containsValue(/*0*/ value: kotlin.Int!): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun forEach(/*0*/ p0: java.util.function.BiConsumer<in kotlin.String!, in kotlin.Int!>!): kotlin.Unit
|
||||
public abstract override /*1*/ /*fake_override*/ fun get(/*0*/ key: kotlin.String!): kotlin.Int?
|
||||
public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ p0: kotlin.Any!, /*1*/ p1: kotlin.Int!): kotlin.Int!
|
||||
@kotlin.internal.PlatformDependent() public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ key: kotlin.String!, /*1*/ defaultValue: kotlin.Int!): kotlin.Int!
|
||||
public abstract override /*1*/ /*fake_override*/ fun isEmpty(): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun merge(/*0*/ p0: kotlin.String!, /*1*/ p1: kotlin.Int!, /*2*/ p2: java.util.function.BiFunction<in kotlin.Int!, in kotlin.Int!, out kotlin.Int!>!): kotlin.Int!
|
||||
public abstract override /*1*/ /*fake_override*/ fun put(/*0*/ key: kotlin.String!, /*1*/ value: kotlin.Int!): kotlin.Int?
|
||||
|
||||
+3
-3
@@ -17,7 +17,7 @@ public open class MapRemove {
|
||||
public abstract override /*1*/ /*fake_override*/ fun containsValue(/*0*/ value: V!): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun forEach(/*0*/ p0: java.util.function.BiConsumer<in K!, in V!>!): kotlin.Unit
|
||||
public abstract override /*1*/ /*fake_override*/ fun get(/*0*/ key: K!): V?
|
||||
public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ p0: kotlin.Any!, /*1*/ p1: V!): V!
|
||||
@kotlin.internal.PlatformDependent() public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ key: K!, /*1*/ defaultValue: V!): V!
|
||||
public abstract override /*1*/ /*fake_override*/ fun isEmpty(): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun merge(/*0*/ p0: K!, /*1*/ p1: V!, /*2*/ p2: java.util.function.BiFunction<in V!, in V!, out V!>!): V!
|
||||
public abstract override /*1*/ /*fake_override*/ fun put(/*0*/ key: K!, /*1*/ value: V!): V?
|
||||
@@ -44,7 +44,7 @@ public open class MapRemove {
|
||||
public abstract override /*1*/ /*fake_override*/ fun containsValue(/*0*/ value: kotlin.Int!): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun forEach(/*0*/ p0: java.util.function.BiConsumer<in kotlin.String!, in kotlin.Int!>!): kotlin.Unit
|
||||
public abstract override /*1*/ /*fake_override*/ fun get(/*0*/ key: kotlin.String!): kotlin.Int?
|
||||
public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ p0: kotlin.Any!, /*1*/ p1: kotlin.Int!): kotlin.Int!
|
||||
@kotlin.internal.PlatformDependent() public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ key: kotlin.String!, /*1*/ defaultValue: kotlin.Int!): kotlin.Int!
|
||||
public abstract override /*1*/ /*fake_override*/ fun isEmpty(): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun merge(/*0*/ p0: kotlin.String!, /*1*/ p1: kotlin.Int!, /*2*/ p2: java.util.function.BiFunction<in kotlin.Int!, in kotlin.Int!, out kotlin.Int!>!): kotlin.Int!
|
||||
public abstract override /*1*/ /*fake_override*/ fun put(/*0*/ key: kotlin.String!, /*1*/ value: kotlin.Int!): kotlin.Int?
|
||||
@@ -71,7 +71,7 @@ public open class MapRemove {
|
||||
public abstract override /*1*/ /*fake_override*/ fun containsValue(/*0*/ value: kotlin.Int!): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun forEach(/*0*/ p0: java.util.function.BiConsumer<in kotlin.String!, in kotlin.Int!>!): kotlin.Unit
|
||||
public abstract override /*1*/ /*fake_override*/ fun get(/*0*/ key: kotlin.String!): kotlin.Int?
|
||||
public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ p0: kotlin.Any!, /*1*/ p1: kotlin.Int!): kotlin.Int!
|
||||
@kotlin.internal.PlatformDependent() public open override /*1*/ /*fake_override*/ fun getOrDefault(/*0*/ key: kotlin.String!, /*1*/ defaultValue: kotlin.Int!): kotlin.Int!
|
||||
public abstract override /*1*/ /*fake_override*/ fun isEmpty(): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun merge(/*0*/ p0: kotlin.String!, /*1*/ p1: kotlin.Int!, /*2*/ p2: java.util.function.BiFunction<in kotlin.Int!, in kotlin.Int!, out kotlin.Int!>!): kotlin.Int!
|
||||
public abstract override /*1*/ /*fake_override*/ fun put(/*0*/ key: kotlin.String!, /*1*/ value: kotlin.Int!): kotlin.Int?
|
||||
|
||||
+6
@@ -139,6 +139,12 @@ public class DiagnosticsWithJava8TestGenerated extends AbstractDiagnosticsWithFu
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("getOrDefault.kt")
|
||||
public void testGetOrDefault() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/getOrDefault.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("mutableMapRemove.kt")
|
||||
public void testMutableMapRemove() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJava8/targetedBuiltIns/mutableMapRemove.kt");
|
||||
|
||||
+27
@@ -179,6 +179,33 @@ public class BlackBoxWithJava8CodegenTestGenerated extends AbstractBlackBoxCodeg
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/java8/box/mapGetOrDefault")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class MapGetOrDefault extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInMapGetOrDefault() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/java8/box/mapGetOrDefault"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("noTypeSafeBridge.kt")
|
||||
public void testNoTypeSafeBridge() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/mapGetOrDefault/noTypeSafeBridge.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("typeSafeBridge.kt")
|
||||
public void testTypeSafeBridge() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/mapGetOrDefault/typeSafeBridge.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("typeSafeBridgeNotNullAny.kt")
|
||||
public void testTypeSafeBridgeNotNullAny() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/mapGetOrDefault/typeSafeBridgeNotNullAny.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/java8/box/mapRemove")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -298,6 +298,17 @@ public interface Map<K, out V> {
|
||||
*/
|
||||
public operator fun get(key: K): V?
|
||||
|
||||
/**
|
||||
* Returns the value corresponding to the given [key], or [defaultValue] if such a key is not present in the map.
|
||||
*
|
||||
* @since JDK 1.8
|
||||
*/
|
||||
@PlatformDependent
|
||||
public fun getOrDefault(key: K, defaultValue: @UnsafeVariance V): V {
|
||||
// See default implementation in JDK sources
|
||||
return null as V
|
||||
}
|
||||
|
||||
// Views
|
||||
/**
|
||||
* Returns a [Set] of all keys in this map.
|
||||
|
||||
+24
-13
@@ -97,34 +97,45 @@ object BuiltinMethodsWithSpecialGenericSignature {
|
||||
|
||||
private val ERASED_COLLECTION_PARAMETER_SIGNATURES = ERASED_COLLECTION_PARAMETER_NAME_AND_SIGNATURES.map { it.signature }
|
||||
|
||||
enum class DefaultValue(val value: Any?) {
|
||||
NULL(null), INDEX(-1), FALSE(false)
|
||||
enum class TypeSafeBarrierDescription(val defaultValue: Any?) {
|
||||
NULL(null), INDEX(-1), FALSE(false),
|
||||
|
||||
MAP_GET_OR_DEFAULT(null) {
|
||||
override fun checkParameter(index: Int) = index != 1
|
||||
};
|
||||
|
||||
open fun checkParameter(index: Int) = true
|
||||
}
|
||||
|
||||
private val GENERIC_PARAMETERS_METHODS_TO_DEFAULT_VALUES_MAP =
|
||||
signatures {
|
||||
mapOf(
|
||||
javaUtil("Collection")
|
||||
.method("contains", "Ljava/lang/Object;", JvmPrimitiveType.BOOLEAN.desc) to DefaultValue.FALSE,
|
||||
.method("contains", "Ljava/lang/Object;", JvmPrimitiveType.BOOLEAN.desc) to TypeSafeBarrierDescription.FALSE,
|
||||
javaUtil("Collection")
|
||||
.method("remove", "Ljava/lang/Object;", JvmPrimitiveType.BOOLEAN.desc) to DefaultValue.FALSE,
|
||||
.method("remove", "Ljava/lang/Object;", JvmPrimitiveType.BOOLEAN.desc) to TypeSafeBarrierDescription.FALSE,
|
||||
|
||||
javaUtil("Map")
|
||||
.method("containsKey", "Ljava/lang/Object;", JvmPrimitiveType.BOOLEAN.desc) to DefaultValue.FALSE,
|
||||
.method("containsKey", "Ljava/lang/Object;", JvmPrimitiveType.BOOLEAN.desc) to TypeSafeBarrierDescription.FALSE,
|
||||
javaUtil("Map")
|
||||
.method("containsValue", "Ljava/lang/Object;", JvmPrimitiveType.BOOLEAN.desc) to DefaultValue.FALSE,
|
||||
.method("containsValue", "Ljava/lang/Object;", JvmPrimitiveType.BOOLEAN.desc) to TypeSafeBarrierDescription.FALSE,
|
||||
javaUtil("Map")
|
||||
.method("remove", "Ljava/lang/Object;Ljava/lang/Object;",
|
||||
JvmPrimitiveType.BOOLEAN.desc) to DefaultValue.FALSE,
|
||||
JvmPrimitiveType.BOOLEAN.desc) to TypeSafeBarrierDescription.FALSE,
|
||||
|
||||
javaUtil("Map")
|
||||
.method("get", "Ljava/lang/Object;", "Ljava/lang/Object;") to DefaultValue.NULL,
|
||||
.method("getOrDefault", "Ljava/lang/Object;Ljava/lang/Object;",
|
||||
"Ljava/lang/Object;") to TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT,
|
||||
|
||||
javaUtil("Map")
|
||||
.method("remove", "Ljava/lang/Object;", "Ljava/lang/Object;") to DefaultValue.NULL,
|
||||
.method("get", "Ljava/lang/Object;", "Ljava/lang/Object;") to TypeSafeBarrierDescription.NULL,
|
||||
javaUtil("Map")
|
||||
.method("remove", "Ljava/lang/Object;", "Ljava/lang/Object;") to TypeSafeBarrierDescription.NULL,
|
||||
|
||||
javaUtil("List")
|
||||
.method("indexOf", "Ljava/lang/Object;", JvmPrimitiveType.INT.desc) to DefaultValue.INDEX,
|
||||
.method("indexOf", "Ljava/lang/Object;", JvmPrimitiveType.INT.desc) to TypeSafeBarrierDescription.INDEX,
|
||||
javaUtil("List")
|
||||
.method("lastIndexOf", "Ljava/lang/Object;", JvmPrimitiveType.INT.desc) to DefaultValue.INDEX
|
||||
.method("lastIndexOf", "Ljava/lang/Object;", JvmPrimitiveType.INT.desc) to TypeSafeBarrierDescription.INDEX
|
||||
)
|
||||
}
|
||||
|
||||
@@ -150,7 +161,7 @@ object BuiltinMethodsWithSpecialGenericSignature {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getDefaultValueForOverriddenBuiltinFunction(functionDescriptor: FunctionDescriptor): DefaultValue? {
|
||||
fun getDefaultValueForOverriddenBuiltinFunction(functionDescriptor: FunctionDescriptor): TypeSafeBarrierDescription? {
|
||||
if (functionDescriptor.name !in ERASED_VALUE_PARAMETERS_SHORT_NAMES) return null
|
||||
return functionDescriptor.firstOverridden {
|
||||
it.computeJvmSignature() in SIGNATURE_TO_DEFAULT_VALUES_MAP.keys
|
||||
@@ -182,7 +193,7 @@ object BuiltinMethodsWithSpecialGenericSignature {
|
||||
|
||||
val defaultValue = SIGNATURE_TO_DEFAULT_VALUES_MAP[builtinSignature]!!
|
||||
|
||||
return if (defaultValue == DefaultValue.NULL)
|
||||
return if (defaultValue == TypeSafeBarrierDescription.NULL)
|
||||
// return type is some generic type as 'Map.get'
|
||||
SpecialSignatureInfo.OBJECT_PARAMETER_GENERIC
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user