From d60818fd3e39c7154848101439d818e76b06d4fa Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Fri, 8 Jun 2012 21:49:31 +0400 Subject: [PATCH] KT-2193 Nullability information lost for functions inherited from traits #KT-2193 fixed --- .../codegen/ImplementationBodyCodegen.java | 51 +++++++++++++++++-- .../testData/codegen/traits/inheritedFun.jet | 10 ++++ .../testData/codegen/traits/inheritedVar.jet | 14 +++++ .../classFun/FunDelegationToTraitImpl.kt | 9 ++++ .../classFun/FunDelegationToTraitImpl.txt | 9 ++++ .../prop/VarDelegationToTraitImpl.kt | 13 +++++ .../prop/VarDelegationToTraitImpl.txt | 9 ++++ .../org/jetbrains/jet/codegen/TraitsTest.java | 8 +++ 8 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/codegen/traits/inheritedFun.jet create mode 100644 compiler/testData/codegen/traits/inheritedVar.jet create mode 100644 compiler/testData/readKotlinBinaryClass/classFun/FunDelegationToTraitImpl.kt create mode 100644 compiler/testData/readKotlinBinaryClass/classFun/FunDelegationToTraitImpl.txt create mode 100644 compiler/testData/readKotlinBinaryClass/prop/VarDelegationToTraitImpl.kt create mode 100644 compiler/testData/readKotlinBinaryClass/prop/VarDelegationToTraitImpl.txt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index cec73ebd275..f366741c4eb 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -23,6 +23,7 @@ import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.codegen.signature.*; +import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter; import org.jetbrains.jet.codegen.signature.kotlin.JetValueParameterAnnotationWriter; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; @@ -720,18 +721,24 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { for (Pair needDelegates : getTraitImplementations(descriptor)) { CallableMemberDescriptor callableDescriptor = needDelegates.first; if (needDelegates.second instanceof SimpleFunctionDescriptor) { - generateDelegationToTraitImpl(codegen, (FunctionDescriptor) needDelegates.second); + generateDelegationToTraitImpl(codegen, (FunctionDescriptor) needDelegates.second, (FunctionDescriptor) needDelegates.first); } else if (needDelegates.second instanceof PropertyDescriptor) { PropertyDescriptor property = (PropertyDescriptor) needDelegates.second; + List inheritedAccessors = ((PropertyDescriptor) needDelegates.first).getAccessors(); for (PropertyAccessorDescriptor accessor : property.getAccessors()) { - generateDelegationToTraitImpl(codegen, accessor); + for (PropertyAccessorDescriptor inheritedAccessor : inheritedAccessors) { + if (inheritedAccessor.getClass() == accessor.getClass()) { // same accessor kind + generateDelegationToTraitImpl(codegen, accessor, inheritedAccessor); + } + } } } } } - private void generateDelegationToTraitImpl(ExpressionCodegen codegen, FunctionDescriptor fun) { + + private void generateDelegationToTraitImpl(ExpressionCodegen codegen, FunctionDescriptor fun, @NotNull FunctionDescriptor inheritedFun) { DeclarationDescriptor containingDeclaration = fun.getContainingDeclaration(); if (containingDeclaration instanceof ClassDescriptor) { ClassDescriptor declaration = (ClassDescriptor) containingDeclaration; @@ -741,10 +748,44 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (jetClass.isTrait()) { int flags = ACC_PUBLIC; // TODO. - Method function = typeMapper.mapSignature(fun.getName(), fun).getAsmMethod(); - Method functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal()).getAsmMethod(); + Method function; + Method functionOriginal; + if (fun instanceof PropertyAccessorDescriptor) { + PropertyDescriptor property = ((PropertyAccessorDescriptor) fun).getCorrespondingProperty(); + if (fun instanceof PropertyGetterDescriptor) { + function = typeMapper.mapGetterSignature(property, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod(); + functionOriginal = typeMapper.mapGetterSignature(property.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod(); + } + else if (fun instanceof PropertySetterDescriptor) { + function = typeMapper.mapSetterSignature(property, OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod(); + functionOriginal = typeMapper.mapSetterSignature(property.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature().getAsmMethod(); + } + else { + throw new IllegalStateException("Accessor is neither getter, nor setter, what is it?"); + } + } + else { + function = typeMapper.mapSignature(fun.getName(), fun).getAsmMethod(); + functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal()).getAsmMethod(); + } final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null); + AnnotationCodegen.forMethod(mv, state.getInjector().getJetTypeMapper()).genAnnotations(fun); + + JvmMethodSignature jvmSignature = typeMapper.mapToCallableMethod(inheritedFun, false, OwnerKind.IMPLEMENTATION).getSignature(); + JetMethodAnnotationWriter aw = JetMethodAnnotationWriter.visitAnnotation(mv); + if (fun instanceof PropertyAccessorDescriptor) { + aw.writeFlags(JvmStdlibNames.JET_METHOD_FLAG_PROPERTY_BIT); + aw.writeTypeParameters(jvmSignature.getKotlinTypeParameter()); + aw.writePropertyType(jvmSignature.getKotlinReturnType()); + } else { + aw.writeFlags(); + aw.writeNullableReturnType(fun.getReturnType().isNullable()); + aw.writeTypeParameters(jvmSignature.getKotlinTypeParameter()); + aw.writeReturnType(jvmSignature.getKotlinReturnType()); + } + aw.visitEnd(); + if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { StubCodegen.generateStubCode(mv); } diff --git a/compiler/testData/codegen/traits/inheritedFun.jet b/compiler/testData/codegen/traits/inheritedFun.jet new file mode 100644 index 00000000000..47fe9223907 --- /dev/null +++ b/compiler/testData/codegen/traits/inheritedFun.jet @@ -0,0 +1,10 @@ +//KT-2206 +trait A { + fun f():Int = 239 +} + +class B() : A + +fun box() : String { + return if (B().f() == 239) "OK" else "fail" +} \ No newline at end of file diff --git a/compiler/testData/codegen/traits/inheritedVar.jet b/compiler/testData/codegen/traits/inheritedVar.jet new file mode 100644 index 00000000000..b24548fad27 --- /dev/null +++ b/compiler/testData/codegen/traits/inheritedVar.jet @@ -0,0 +1,14 @@ +//KT-2206 + +trait A { + var a:Int + get() = 239 + set(value) { + } +} + +class B() : A + +fun box() : String { + return if (B().a == 239) "OK" else "fail" +} \ No newline at end of file diff --git a/compiler/testData/readKotlinBinaryClass/classFun/FunDelegationToTraitImpl.kt b/compiler/testData/readKotlinBinaryClass/classFun/FunDelegationToTraitImpl.kt new file mode 100644 index 00000000000..4b0dcb7b986 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classFun/FunDelegationToTraitImpl.kt @@ -0,0 +1,9 @@ +package test + +// test composed from KT-2193 + +trait A { + open fun f(): String = "test" +} + +class B() : A \ No newline at end of file diff --git a/compiler/testData/readKotlinBinaryClass/classFun/FunDelegationToTraitImpl.txt b/compiler/testData/readKotlinBinaryClass/classFun/FunDelegationToTraitImpl.txt new file mode 100644 index 00000000000..38249f2f6c7 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/classFun/FunDelegationToTraitImpl.txt @@ -0,0 +1,9 @@ +namespace test + +abstract trait test.A : jet.Any { + open fun f(): jet.String +} +final class test.B : test.A { + final /*constructor*/ fun (): test.B + open override /*1*/ fun f(): jet.String +} diff --git a/compiler/testData/readKotlinBinaryClass/prop/VarDelegationToTraitImpl.kt b/compiler/testData/readKotlinBinaryClass/prop/VarDelegationToTraitImpl.kt new file mode 100644 index 00000000000..819754f5272 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/prop/VarDelegationToTraitImpl.kt @@ -0,0 +1,13 @@ +package test + +// test composed from KT-2193 + +trait A { + open var v: String + get() = "test" + set(value) { + throw UnsupportedOperationException() + } +} + +class B() : A \ No newline at end of file diff --git a/compiler/testData/readKotlinBinaryClass/prop/VarDelegationToTraitImpl.txt b/compiler/testData/readKotlinBinaryClass/prop/VarDelegationToTraitImpl.txt new file mode 100644 index 00000000000..b342f5730d3 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/prop/VarDelegationToTraitImpl.txt @@ -0,0 +1,9 @@ +namespace test + +abstract trait test.A : jet.Any { + open var v: jet.String +} +final class test.B : test.A { + final /*constructor*/ fun (): test.B + open var v: jet.String +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/TraitsTest.java b/compiler/tests/org/jetbrains/jet/codegen/TraitsTest.java index f690a0791d5..7bce2e8163f 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/TraitsTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/TraitsTest.java @@ -48,4 +48,12 @@ public class TraitsTest extends CodegenTestCase { public void testStdlib () throws Exception { blackBoxFile("traits/stdlib.jet"); } + + public void testInheritedFun() throws Exception { + blackBoxFile("traits/inheritedFun.jet"); + } + + public void testInheritedVar() throws Exception { + blackBoxFile("traits/inheritedVar.jet"); + } }