From fbf9f5f7d0fd5779f4077a6e6b709523407dcbb5 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 21 Apr 2014 16:37:08 +0400 Subject: [PATCH] Don't generate bridges for equals(), hashCode(), toString() Otherwise an assertion is failing in the algorithm which is related to an inconsistency of java.lang.Object inheritance in JDR (KT-4890) --- .../jet/codegen/FunctionCodegen.java | 17 +++++++++++++++ .../codegen/box/bridges/objectClone.kt | 21 +++++++++++++++++++ .../box/classes/inheritSetAndHashSet.kt | 11 ++++++++++ .../BlackBoxCodegenTestGenerated.java | 10 +++++++++ 4 files changed, 59 insertions(+) create mode 100644 compiler/testData/codegen/box/bridges/objectClone.kt create mode 100644 compiler/testData/codegen/box/classes/inheritSetAndHashSet.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 51e2339e260..52a96243eb5 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -47,6 +47,7 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.JavaClassValue; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.name.FqName; +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.org.objectweb.asm.AnnotationVisitor; import org.jetbrains.org.objectweb.asm.Label; import org.jetbrains.org.objectweb.asm.MethodVisitor; @@ -427,6 +428,9 @@ public class FunctionCodegen extends ParentCodegenAwareImpl { if (owner.getContextKind() == OwnerKind.TRAIT_IMPL) return; if (isTrait(descriptor.getContainingDeclaration())) return; + // equals(Any?), hashCode(), toString() never need bridges + if (isMethodOfAny(descriptor)) return; + // If the function doesn't have a physical declaration among super-functions, it's a SAM adapter or alike and doesn't need bridges if (CallResolverUtil.isOrOverridesSynthesized(descriptor)) return; @@ -448,6 +452,19 @@ public class FunctionCodegen extends ParentCodegenAwareImpl { } } + private static boolean isMethodOfAny(@NotNull FunctionDescriptor descriptor) { + String name = descriptor.getName().asString(); + List parameters = descriptor.getValueParameters(); + if (parameters.isEmpty()) { + return name.equals("hashCode") || name.equals("toString"); + } + else if (parameters.size() == 1 && name.equals("equals")) { + ValueParameterDescriptor parameter = parameters.get(0); + return parameter.getType().equals(KotlinBuiltIns.getInstance().getNullableAnyType()); + } + return false; + } + @NotNull private static String[] getThrownExceptions(@NotNull FunctionDescriptor function, @NotNull final JetTypeMapper mapper) { AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.throws")); diff --git a/compiler/testData/codegen/box/bridges/objectClone.kt b/compiler/testData/codegen/box/bridges/objectClone.kt new file mode 100644 index 00000000000..190a46d0c23 --- /dev/null +++ b/compiler/testData/codegen/box/bridges/objectClone.kt @@ -0,0 +1,21 @@ +import java.util.HashSet + +trait A : Set + +class B : A, HashSet() { + override fun clone(): B = throw AssertionError() +} + +fun box(): String { + return try { + B().clone() + "Fail 1" + } catch (e: AssertionError) { + try { + (B() : HashSet).clone() + "Fail 2" + } catch (e: AssertionError) { + "OK" + } + } +} diff --git a/compiler/testData/codegen/box/classes/inheritSetAndHashSet.kt b/compiler/testData/codegen/box/classes/inheritSetAndHashSet.kt new file mode 100644 index 00000000000..b7711f77748 --- /dev/null +++ b/compiler/testData/codegen/box/classes/inheritSetAndHashSet.kt @@ -0,0 +1,11 @@ +import java.util.HashSet + +trait A : Set + +class B : A, HashSet() + +fun box(): String { + val b = B() + b.add("OK") + return b.iterator().next() +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index 4b201ef249b..a240c59f47a 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -405,6 +405,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/bridges/noBridgeOnMutableCollectionInheritance.kt"); } + @TestMetadata("objectClone.kt") + public void testObjectClone() throws Exception { + doTest("compiler/testData/codegen/box/bridges/objectClone.kt"); + } + @TestMetadata("overrideAbstractProperty.kt") public void testOverrideAbstractProperty() throws Exception { doTest("compiler/testData/codegen/box/bridges/overrideAbstractProperty.kt"); @@ -1086,6 +1091,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/classes/funDelegation.kt"); } + @TestMetadata("inheritSetAndHashSet.kt") + public void testInheritSetAndHashSet() throws Exception { + doTest("compiler/testData/codegen/box/classes/inheritSetAndHashSet.kt"); + } + @TestMetadata("inheritance.kt") public void testInheritance() throws Exception { doTest("compiler/testData/codegen/box/classes/inheritance.kt");