diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index cf7e21e1064..99ea259ad92 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -284,6 +284,8 @@ public class ExpressionCodegen extends JetVisitor implem runtimeAssertionInfo = bindingContext.get(BindingContextSlicesKt.getRUNTIME_ASSERTION_INFO(), (JetExpression) selector); } + if (BuiltinSpecialBridgesKt.isValueArgumentForCallToMethodWithTypeCheckBarrier(selector, bindingContext)) return stackValue; + return genNotNullAssertions(state, stackValue, runtimeAssertionInfo); } catch (ProcessCanceledException e) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/builtinSpecialBridges.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/builtinSpecialBridges.kt index ada93d726b6..2ad7bd71fa3 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/builtinSpecialBridges.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/builtinSpecialBridges.kt @@ -18,9 +18,19 @@ package org.jetbrains.kotlin.codegen import org.jetbrains.kotlin.backend.common.bridges.* import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature +import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.load.java.getOverriddenBuiltinWithDifferentJvmDescriptor +import org.jetbrains.kotlin.psi.JetCallElement +import org.jetbrains.kotlin.psi.JetElement +import org.jetbrains.kotlin.psi.JetPsiUtil +import org.jetbrains.kotlin.psi.JetValueArgument +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.calls.callUtil.getParentCall +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure import org.jetbrains.kotlin.utils.singletonOrEmptyList @@ -123,3 +133,23 @@ private fun needGenerateSpecialBridge( return true } + +public fun isValueArgumentForCallToMethodWithTypeCheckBarrier( + element: JetElement, + bindingContext: BindingContext +): Boolean { + + val parentCall = element.getParentCall(bindingContext, strict = true) ?: return false + val argumentExpression = parentCall.valueArguments.singleOrNull()?.getArgumentExpression() ?: return false + if (JetPsiUtil.deparenthesize(argumentExpression) !== element) return false + + val candidateDescriptor = parentCall.getResolvedCall(bindingContext)?.candidateDescriptor as CallableMemberDescriptor? + ?: return false + + + if (candidateDescriptor.getSpecialSignatureInfo() == BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo.GENERIC_PARAMETER) { + return true + } + + return false +} diff --git a/compiler/testData/codegen/boxWithJava/collections/platformValueContains/J.java b/compiler/testData/codegen/boxWithJava/collections/platformValueContains/J.java new file mode 100644 index 00000000000..2f9e2cb1da2 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/collections/platformValueContains/J.java @@ -0,0 +1,7 @@ +import java.util.*; + +public class J { + public static String nullValue() { + return null; + } +} diff --git a/compiler/testData/codegen/boxWithJava/collections/platformValueContains/platformValueContains.kt b/compiler/testData/codegen/boxWithJava/collections/platformValueContains/platformValueContains.kt new file mode 100644 index 00000000000..8172f14bfb8 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/collections/platformValueContains/platformValueContains.kt @@ -0,0 +1,40 @@ +class MySet : Set { + override val size: Int + get() = throw UnsupportedOperationException() + + override fun isEmpty(): Boolean { + throw UnsupportedOperationException() + } + + override fun contains(o: String): Boolean { + throw UnsupportedOperationException() + } + + override fun iterator(): Iterator { + throw UnsupportedOperationException() + } + + override fun containsAll(c: Collection): Boolean { + throw UnsupportedOperationException() + } +} + +fun box(): String { + val mySet = MySet() + + // no UnsupportedOperationException thrown + mySet.contains(J.nullValue()) + J.nullValue() in mySet + + val set: Set = mySet + set.contains(J.nullValue()) + J.nullValue() in set + + val anySet: Set = mySet as Set + anySet.contains(J.nullValue()) + anySet.contains(null) + J.nullValue() in anySet + null in anySet + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java index 5674bb9177f..09cbd9dee28 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java @@ -197,6 +197,12 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege doTestWithJava(fileName); } + @TestMetadata("platformValueContains") + public void testPlatformValueContains() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/collections/platformValueContains/"); + doTestWithJava(fileName); + } + @TestMetadata("removeAtInt") public void testRemoveAtInt() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/collections/removeAtInt/");