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)
This commit is contained in:
Alexander Udalov
2014-04-21 16:37:08 +04:00
parent 6b348bfc6e
commit fbf9f5f7d0
4 changed files with 59 additions and 0 deletions
@@ -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<ValueParameterDescriptor> 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"));
@@ -0,0 +1,21 @@
import java.util.HashSet
trait A : Set<String>
class B : A, HashSet<String>() {
override fun clone(): B = throw AssertionError()
}
fun box(): String {
return try {
B().clone()
"Fail 1"
} catch (e: AssertionError) {
try {
(B() : HashSet<String>).clone()
"Fail 2"
} catch (e: AssertionError) {
"OK"
}
}
}
@@ -0,0 +1,11 @@
import java.util.HashSet
trait A : Set<String>
class B : A, HashSet<String>()
fun box(): String {
val b = B()
b.add("OK")
return b.iterator().next()
}
@@ -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");