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:
Denis Zharkov
2015-11-24 17:19:15 +03:00
parent 20cbceb56d
commit 6292833a69
8 changed files with 73 additions and 27 deletions
@@ -108,15 +108,13 @@ class CollectionStubMethodGenerator(
val genericSignatureInfo = overriddenMethod.getSpecialSignatureInfo()
val specialGenericSignature =
if (genericSignatureInfo != null)
genericSignatureInfo.signature
else
overriddenMethodSignature.genericsSignature
genericSignatureInfo?.replaceValueParametersIn(overriddenMethodSignature.genericsSignature)
?: overriddenMethodSignature.genericsSignature
val (asmMethod, valueParameters) =
// if remove(E) in Kotlin -> remove(Object) in Java
// so choose original signature
if (genericSignatureInfo == SpecialSignatureInfo.GENERIC_PARAMETER)
// if current method has special generic signature,
// like `Collection.remove(E): Boolean` in Kotlin, use original signature to obtain `remove(Object)`
if (genericSignatureInfo?.isObjectReplacedWithTypeParameter ?: false)
Pair(originalSignature.asmMethod, originalSignature.valueParameters)
else
Pair(overriddenMethodSignature.asmMethod, overriddenMethodSignature.valueParameters)
@@ -153,12 +153,7 @@ public fun isValueArgumentForCallToMethodWithTypeCheckBarrier(
if (KtPsiUtil.deparenthesize(argumentExpression) !== element) return false
val candidateDescriptor = parentCall.getResolvedCall(bindingContext)?.candidateDescriptor as CallableMemberDescriptor?
?: return false
?: return false
if (candidateDescriptor.getSpecialSignatureInfo() == BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo.GENERIC_PARAMETER) {
return true
}
return false
return candidateDescriptor.getSpecialSignatureInfo()?.isObjectReplacedWithTypeParameter ?: false
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -49,3 +50,7 @@ fun generateIsCheck(
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);
if (specialSignatureInfo != null) {
return new JvmMethodSignature(
signature.getAsmMethod(), specialSignatureInfo.getSignature(), signature.getValueParameters());
String newGenericSignature = CodegenUtilKt.replaceValueParametersIn(
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()
@@ -293,6 +293,12 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
doTestWithJava(fileName);
}
@TestMetadata("readOnlyMap")
public void testReadOnlyMap() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/collections/readOnlyMap/");
doTestWithJava(fileName);
}
@TestMetadata("removeAtInt")
public void testRemoveAtInt() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/collections/removeAtInt/");