IR: check absence of extension receiver in isMethodOfAny

Otherwise extension methods named toString/equals/hashCode were
generated incorrectly on JVM IR, which could result in
AbstractMethodError at runtime.

 #KT-45963 Fixed
This commit is contained in:
Alexander Udalov
2021-04-09 21:53:06 +02:00
parent 98d31a1813
commit ea22f4b681
10 changed files with 69 additions and 3 deletions
@@ -14738,6 +14738,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/extensionFunctions/kt865.kt");
}
@Test
@TestMetadata("memberExtensionEqualsHashCodeToStringInInterface.kt")
public void testMemberExtensionEqualsHashCodeToStringInInterface() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/memberExtensionEqualsHashCodeToStringInInterface.kt");
}
@Test
@TestMetadata("nested2.kt")
public void testNested2() throws Exception {
@@ -394,9 +394,13 @@ fun IrClass.createImplicitParameterDeclarationWithWrappedDescriptor() {
@Suppress("UNCHECKED_CAST")
fun isElseBranch(branch: IrBranch) = branch is IrElseBranch || ((branch.condition as? IrConst<Boolean>)?.value == true)
fun IrFunction.isMethodOfAny() =
((valueParameters.size == 0 && name.asString().let { it == "hashCode" || it == "toString" }) ||
(valueParameters.size == 1 && name.asString() == "equals" && valueParameters[0].type.isNullableAny()))
fun IrFunction.isMethodOfAny(): Boolean =
extensionReceiverParameter == null && dispatchReceiverParameter != null &&
when (name.asString()) {
"hashCode", "toString" -> valueParameters.isEmpty()
"equals" -> valueParameters.singleOrNull()?.type?.isNullableAny() == true
else -> false
}
fun IrClass.simpleFunctions() = declarations.flatMap {
when (it) {
@@ -0,0 +1,19 @@
interface AssertDSL {
infix fun Any?.equals(other: Any?) {
if (this != other) throw AssertionError("$this != $other")
}
fun Any?.toString(): String = ""
fun Any?.hashCode(): Int = 0
}
class C(val x: Int) : AssertDSL
fun C.test(): String {
x equals 42
null.toString()
null.hashCode()
return "OK"
}
fun box(): String = C(42).test()
@@ -14738,6 +14738,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/extensionFunctions/kt865.kt");
}
@Test
@TestMetadata("memberExtensionEqualsHashCodeToStringInInterface.kt")
public void testMemberExtensionEqualsHashCodeToStringInInterface() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/memberExtensionEqualsHashCodeToStringInInterface.kt");
}
@Test
@TestMetadata("nested2.kt")
public void testNested2() throws Exception {
@@ -14738,6 +14738,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/extensionFunctions/kt865.kt");
}
@Test
@TestMetadata("memberExtensionEqualsHashCodeToStringInInterface.kt")
public void testMemberExtensionEqualsHashCodeToStringInInterface() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/memberExtensionEqualsHashCodeToStringInInterface.kt");
}
@Test
@TestMetadata("nested2.kt")
public void testNested2() throws Exception {
@@ -12095,6 +12095,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/extensionFunctions/kt865.kt");
}
@TestMetadata("memberExtensionEqualsHashCodeToStringInInterface.kt")
public void testMemberExtensionEqualsHashCodeToStringInInterface() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/memberExtensionEqualsHashCodeToStringInInterface.kt");
}
@TestMetadata("nested2.kt")
public void testNested2() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/nested2.kt");
@@ -10764,6 +10764,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/extensionFunctions/kt865.kt");
}
@TestMetadata("memberExtensionEqualsHashCodeToStringInInterface.kt")
public void testMemberExtensionEqualsHashCodeToStringInInterface() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/memberExtensionEqualsHashCodeToStringInInterface.kt");
}
@TestMetadata("nested2.kt")
public void testNested2() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/nested2.kt");
@@ -10185,6 +10185,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/extensionFunctions/kt865.kt");
}
@TestMetadata("memberExtensionEqualsHashCodeToStringInInterface.kt")
public void testMemberExtensionEqualsHashCodeToStringInInterface() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/memberExtensionEqualsHashCodeToStringInInterface.kt");
}
@TestMetadata("nested2.kt")
public void testNested2() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/nested2.kt");
@@ -10185,6 +10185,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/extensionFunctions/kt865.kt");
}
@TestMetadata("memberExtensionEqualsHashCodeToStringInInterface.kt")
public void testMemberExtensionEqualsHashCodeToStringInInterface() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/memberExtensionEqualsHashCodeToStringInInterface.kt");
}
@TestMetadata("nested2.kt")
public void testNested2() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/nested2.kt");
@@ -5089,6 +5089,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/extensionFunctions/kt5467.kt");
}
@TestMetadata("memberExtensionEqualsHashCodeToStringInInterface.kt")
public void testMemberExtensionEqualsHashCodeToStringInInterface() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/memberExtensionEqualsHashCodeToStringInInterface.kt");
}
@TestMetadata("nested2.kt")
public void testNested2() throws Exception {
runTest("compiler/testData/codegen/box/extensionFunctions/nested2.kt");