Refine generic signature for Map.get/remove
Before this change generic signature wasn't written because of wrong assumption about it absence in all cases where we replace generic parameter with Object
This commit is contained in:
@@ -108,15 +108,13 @@ class CollectionStubMethodGenerator(
|
|||||||
val genericSignatureInfo = overriddenMethod.getSpecialSignatureInfo()
|
val genericSignatureInfo = overriddenMethod.getSpecialSignatureInfo()
|
||||||
|
|
||||||
val specialGenericSignature =
|
val specialGenericSignature =
|
||||||
if (genericSignatureInfo != null)
|
genericSignatureInfo?.replaceValueParametersIn(overriddenMethodSignature.genericsSignature)
|
||||||
genericSignatureInfo.signature
|
?: overriddenMethodSignature.genericsSignature
|
||||||
else
|
|
||||||
overriddenMethodSignature.genericsSignature
|
|
||||||
|
|
||||||
val (asmMethod, valueParameters) =
|
val (asmMethod, valueParameters) =
|
||||||
// if remove(E) in Kotlin -> remove(Object) in Java
|
// if current method has special generic signature,
|
||||||
// so choose original signature
|
// like `Collection.remove(E): Boolean` in Kotlin, use original signature to obtain `remove(Object)`
|
||||||
if (genericSignatureInfo == SpecialSignatureInfo.GENERIC_PARAMETER)
|
if (genericSignatureInfo?.isObjectReplacedWithTypeParameter ?: false)
|
||||||
Pair(originalSignature.asmMethod, originalSignature.valueParameters)
|
Pair(originalSignature.asmMethod, originalSignature.valueParameters)
|
||||||
else
|
else
|
||||||
Pair(overriddenMethodSignature.asmMethod, overriddenMethodSignature.valueParameters)
|
Pair(overriddenMethodSignature.asmMethod, overriddenMethodSignature.valueParameters)
|
||||||
|
|||||||
@@ -153,12 +153,7 @@ public fun isValueArgumentForCallToMethodWithTypeCheckBarrier(
|
|||||||
if (KtPsiUtil.deparenthesize(argumentExpression) !== element) return false
|
if (KtPsiUtil.deparenthesize(argumentExpression) !== element) return false
|
||||||
|
|
||||||
val candidateDescriptor = parentCall.getResolvedCall(bindingContext)?.candidateDescriptor as CallableMemberDescriptor?
|
val candidateDescriptor = parentCall.getResolvedCall(bindingContext)?.candidateDescriptor as CallableMemberDescriptor?
|
||||||
?: return false
|
?: return false
|
||||||
|
|
||||||
|
return candidateDescriptor.getSpecialSignatureInfo()?.isObjectReplacedWithTypeParameter ?: false
|
||||||
if (candidateDescriptor.getSpecialSignatureInfo() == BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo.GENERIC_PARAMETER) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||||
@@ -49,3 +50,7 @@ fun generateIsCheck(
|
|||||||
generateInstanceOfInstruction(v)
|
generateInstanceOfInstruction(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public fun SpecialSignatureInfo.replaceValueParametersIn(sourceSignature: String?): String?
|
||||||
|
= valueParametersSignature?.let { sourceSignature?.replace("^\\(.*\\)".toRegex(), "($it)") }
|
||||||
|
|||||||
@@ -1006,8 +1006,9 @@ public class JetTypeMapper {
|
|||||||
SpecialSignatureInfo specialSignatureInfo = BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo(f);
|
SpecialSignatureInfo specialSignatureInfo = BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo(f);
|
||||||
|
|
||||||
if (specialSignatureInfo != null) {
|
if (specialSignatureInfo != null) {
|
||||||
return new JvmMethodSignature(
|
String newGenericSignature = CodegenUtilKt.replaceValueParametersIn(
|
||||||
signature.getAsmMethod(), specialSignatureInfo.getSignature(), signature.getValueParameters());
|
specialSignatureInfo, signature.getGenericsSignature());
|
||||||
|
return new JvmMethodSignature(signature.getAsmMethod(), newGenericSignature, signature.getValueParameters());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class J {
|
||||||
|
|
||||||
|
private static class MyMap<K, V> extends KMap<K, V> {}
|
||||||
|
|
||||||
|
public static String foo() {
|
||||||
|
Map<String, Integer> collection = new MyMap<String, Integer>();
|
||||||
|
if (!collection.containsKey("ABCDE")) return "fail 1";
|
||||||
|
if (!collection.containsValue(1)) return "fail 2";
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
open class KMap<K, V> : Map<K, V> {
|
||||||
|
override val size: Int
|
||||||
|
get() = throw UnsupportedOperationException()
|
||||||
|
|
||||||
|
override fun isEmpty(): Boolean {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun containsKey(key: K) = true
|
||||||
|
override fun containsValue(value: V) = true
|
||||||
|
|
||||||
|
override fun get(key: K): V? {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val keys: Set<K>
|
||||||
|
get() = throw UnsupportedOperationException()
|
||||||
|
override val values: Collection<V>
|
||||||
|
get() = throw UnsupportedOperationException()
|
||||||
|
override val entries: Set<Map.Entry<K, V>>
|
||||||
|
get() = throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() = J.foo()
|
||||||
+6
@@ -293,6 +293,12 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
|
|||||||
doTestWithJava(fileName);
|
doTestWithJava(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("readOnlyMap")
|
||||||
|
public void testReadOnlyMap() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/collections/readOnlyMap/");
|
||||||
|
doTestWithJava(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("removeAtInt")
|
@TestMetadata("removeAtInt")
|
||||||
public void testRemoveAtInt() throws Exception {
|
public void testRemoveAtInt() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/collections/removeAtInt/");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/collections/removeAtInt/");
|
||||||
|
|||||||
+15
-11
@@ -124,14 +124,15 @@ object BuiltinMethodsWithSpecialGenericSignature {
|
|||||||
val Name.sameAsBuiltinMethodWithErasedValueParameters: Boolean
|
val Name.sameAsBuiltinMethodWithErasedValueParameters: Boolean
|
||||||
get () = this in ERASED_VALUE_PARAMETERS_SHORT_NAMES
|
get () = this in ERASED_VALUE_PARAMETERS_SHORT_NAMES
|
||||||
|
|
||||||
enum class SpecialSignatureInfo(val signature: String?) {
|
enum class SpecialSignatureInfo(val valueParametersSignature: String?, val isObjectReplacedWithTypeParameter: Boolean) {
|
||||||
ONE_COLLECTION_PARAMETER("(Ljava/util/Collection<+Ljava/lang/Object;>;)Z"),
|
ONE_COLLECTION_PARAMETER("Ljava/util/Collection<+Ljava/lang/Object;>;", false),
|
||||||
GENERIC_PARAMETER(null)
|
OBJECT_PARAMETER_NON_GENERIC(null, true),
|
||||||
|
OBJECT_PARAMETER_GENERIC("Ljava/lang/Object;", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CallableMemberDescriptor.isBuiltinWithSpecialDescriptorInJvm(): Boolean {
|
fun CallableMemberDescriptor.isBuiltinWithSpecialDescriptorInJvm(): Boolean {
|
||||||
if (!isFromBuiltins()) return false
|
if (!isFromBuiltins()) return false
|
||||||
return getSpecialSignatureInfo() == SpecialSignatureInfo.GENERIC_PARAMETER || doesOverrideBuiltinWithDifferentJvmName()
|
return getSpecialSignatureInfo()?.isObjectReplacedWithTypeParameter ?: false || doesOverrideBuiltinWithDifferentJvmName()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@@ -139,11 +140,15 @@ object BuiltinMethodsWithSpecialGenericSignature {
|
|||||||
val builtinFqName = firstOverridden { it is FunctionDescriptor && it.hasErasedValueParametersInJava }?.fqNameOrNull()
|
val builtinFqName = firstOverridden { it is FunctionDescriptor && it.hasErasedValueParametersInJava }?.fqNameOrNull()
|
||||||
?: return null
|
?: return null
|
||||||
|
|
||||||
return when (builtinFqName) {
|
if (builtinFqName in ERASED_COLLECTION_PARAMETER_FQ_NAMES) return SpecialSignatureInfo.ONE_COLLECTION_PARAMETER
|
||||||
in ERASED_COLLECTION_PARAMETER_FQ_NAMES -> SpecialSignatureInfo.ONE_COLLECTION_PARAMETER
|
|
||||||
in GENERIC_PARAMETERS_METHODS_TO_DEFAULT_VALUES_MAP -> SpecialSignatureInfo.GENERIC_PARAMETER
|
val defaultValue = GENERIC_PARAMETERS_METHODS_TO_DEFAULT_VALUES_MAP[builtinFqName]!!
|
||||||
else -> error("Unexpected kind of special builtin: $builtinFqName")
|
|
||||||
}
|
return if (defaultValue == DefaultValue.NULL)
|
||||||
|
// return type is some generic type as 'Map.get'
|
||||||
|
SpecialSignatureInfo.OBJECT_PARAMETER_GENERIC
|
||||||
|
else
|
||||||
|
SpecialSignatureInfo.OBJECT_PARAMETER_NON_GENERIC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,8 +212,7 @@ fun <T : CallableMemberDescriptor> T.getOverriddenBuiltinWithDifferentJvmDescrip
|
|||||||
if (!name.sameAsBuiltinMethodWithErasedValueParameters) return null
|
if (!name.sameAsBuiltinMethodWithErasedValueParameters) return null
|
||||||
|
|
||||||
return firstOverridden {
|
return firstOverridden {
|
||||||
it.isFromBuiltins()
|
it.isFromBuiltins() && it.getSpecialSignatureInfo()?.isObjectReplacedWithTypeParameter ?: false
|
||||||
&& it.getSpecialSignatureInfo() == BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo.GENERIC_PARAMETER
|
|
||||||
}?.original as T?
|
}?.original as T?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user