From 3a5d0ab427105e959aca4de2ad538a6757675518 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 3 Sep 2020 20:09:49 +0200 Subject: [PATCH] JVM IR: fix HashCode intrinsic for generics substituted with primitives The problem here was that although the IR type of the expression was primitive, the type of the actual expression in the bytecode generated after type erasure was `Ljava/lang/Object;`, and we were trying to call a non-existing method `Object.hashCode(Object)`. #KT-41669 Fixed --- .../codegen/ir/FirBlackBoxCodegenTestGenerated.java | 5 +++++ .../kotlin/backend/jvm/intrinsics/HashCode.kt | 5 +++-- .../ir/hashCodeOnGenericSubstitutedWithPrimitive.kt | 11 +++++++++++ .../kotlin/codegen/BlackBoxCodegenTestGenerated.java | 5 +++++ .../codegen/LightAnalysisModeTestGenerated.java | 5 +++++ .../codegen/ir/IrBlackBoxCodegenTestGenerated.java | 5 +++++ .../es6/semantics/IrJsCodegenBoxES6TestGenerated.java | 5 +++++ .../ir/semantics/IrJsCodegenBoxTestGenerated.java | 5 +++++ .../js/test/semantics/JsCodegenBoxTestGenerated.java | 5 +++++ 9 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/codegen/box/ir/hashCodeOnGenericSubstitutedWithPrimitive.kt diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 3df7305f368..db345e7f85b 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -14878,6 +14878,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/ir/genericCompanion.kt"); } + @TestMetadata("hashCodeOnGenericSubstitutedWithPrimitive.kt") + public void testHashCodeOnGenericSubstitutedWithPrimitive() throws Exception { + runTest("compiler/testData/codegen/box/ir/hashCodeOnGenericSubstitutedWithPrimitive.kt"); + } + @TestMetadata("kt25405.kt") public void testKt25405() throws Exception { runTest("compiler/testData/codegen/box/ir/kt25405.kt"); diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/HashCode.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/HashCode.kt index 751882f4ca8..1511e4de4db 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/HashCode.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/HashCode.kt @@ -33,9 +33,10 @@ object HashCode : IntrinsicMethod() { val result = receiver.accept(this, data).materialized() val target = context.state.target when { - irFunction.origin == JvmLoweredDeclarationOrigin.INLINE_CLASS_GENERATED_IMPL_METHOD || irFunction.origin == IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER -> + irFunction.origin == JvmLoweredDeclarationOrigin.INLINE_CLASS_GENERATED_IMPL_METHOD || + irFunction.origin == IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER -> AsmUtil.genHashCode(mv, mv, result.type, target) - target == JvmTarget.JVM_1_6 -> { + target == JvmTarget.JVM_1_6 || !AsmUtil.isPrimitive(result.type) -> { result.materializeAtBoxed(receiver.type) mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "hashCode", "()I", false) } diff --git a/compiler/testData/codegen/box/ir/hashCodeOnGenericSubstitutedWithPrimitive.kt b/compiler/testData/codegen/box/ir/hashCodeOnGenericSubstitutedWithPrimitive.kt new file mode 100644 index 00000000000..8c2ccab73b1 --- /dev/null +++ b/compiler/testData/codegen/box/ir/hashCodeOnGenericSubstitutedWithPrimitive.kt @@ -0,0 +1,11 @@ +// JVM_TARGET: 1.8 + +class A { + fun id(x: T): T = x +} + +fun foo(f: A): Int = + f.id(true).hashCode() + +fun box(): String = + if (foo(A()) == true.hashCode()) "OK" else "Fail" diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 056acf2dd5b..469ad6aa402 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -16103,6 +16103,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/ir/genericCompanion.kt"); } + @TestMetadata("hashCodeOnGenericSubstitutedWithPrimitive.kt") + public void testHashCodeOnGenericSubstitutedWithPrimitive() throws Exception { + runTest("compiler/testData/codegen/box/ir/hashCodeOnGenericSubstitutedWithPrimitive.kt"); + } + @TestMetadata("kt25405.kt") public void testKt25405() throws Exception { runTest("compiler/testData/codegen/box/ir/kt25405.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 2cb8efe94e9..456f5675927 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -16103,6 +16103,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/ir/genericCompanion.kt"); } + @TestMetadata("hashCodeOnGenericSubstitutedWithPrimitive.kt") + public void testHashCodeOnGenericSubstitutedWithPrimitive() throws Exception { + runTest("compiler/testData/codegen/box/ir/hashCodeOnGenericSubstitutedWithPrimitive.kt"); + } + @TestMetadata("kt25405.kt") public void testKt25405() throws Exception { runTest("compiler/testData/codegen/box/ir/kt25405.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 9d2f3b15aed..8b665281b09 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -14878,6 +14878,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/ir/genericCompanion.kt"); } + @TestMetadata("hashCodeOnGenericSubstitutedWithPrimitive.kt") + public void testHashCodeOnGenericSubstitutedWithPrimitive() throws Exception { + runTest("compiler/testData/codegen/box/ir/hashCodeOnGenericSubstitutedWithPrimitive.kt"); + } + @TestMetadata("kt25405.kt") public void testKt25405() throws Exception { runTest("compiler/testData/codegen/box/ir/kt25405.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index ab452542399..3ec9d8e69b0 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -12893,6 +12893,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/ir/genericCompanion.kt"); } + @TestMetadata("hashCodeOnGenericSubstitutedWithPrimitive.kt") + public void testHashCodeOnGenericSubstitutedWithPrimitive() throws Exception { + runTest("compiler/testData/codegen/box/ir/hashCodeOnGenericSubstitutedWithPrimitive.kt"); + } + @TestMetadata("kt25405.kt") public void testKt25405() throws Exception { runTest("compiler/testData/codegen/box/ir/kt25405.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 4fcade78f06..c2a600dd21f 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -12893,6 +12893,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/ir/genericCompanion.kt"); } + @TestMetadata("hashCodeOnGenericSubstitutedWithPrimitive.kt") + public void testHashCodeOnGenericSubstitutedWithPrimitive() throws Exception { + runTest("compiler/testData/codegen/box/ir/hashCodeOnGenericSubstitutedWithPrimitive.kt"); + } + @TestMetadata("kt25405.kt") public void testKt25405() throws Exception { runTest("compiler/testData/codegen/box/ir/kt25405.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 47e88caf701..3d5cd82e26a 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -12958,6 +12958,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/ir/genericCompanion.kt"); } + @TestMetadata("hashCodeOnGenericSubstitutedWithPrimitive.kt") + public void testHashCodeOnGenericSubstitutedWithPrimitive() throws Exception { + runTest("compiler/testData/codegen/box/ir/hashCodeOnGenericSubstitutedWithPrimitive.kt"); + } + @TestMetadata("kt25405.kt") public void testKt25405() throws Exception { runTest("compiler/testData/codegen/box/ir/kt25405.kt");