diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index a12c3193732..0d346dac21b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -818,6 +818,8 @@ public class FunctionCodegen extends GenerationStateAware { iv.areturn(delegateMethod.getReturnType()); endVisit(mv, "delegate method", descriptorToDeclaration(bindingContext, functionDescriptor)); + + generateBridgeIfNeeded(owner, state, v, jvmDelegateMethodSignature.getAsmMethod(), functionDescriptor); } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index 074a239668b..944677ad8bf 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -316,17 +316,17 @@ public class PropertyCodegen extends GenerationStateAware { return JvmAbi.SETTER_PREFIX + StringUtil.capitalizeWithJavaBeanConvention(propertyName.getName()); } - public void genDelegate(PropertyDescriptor declaration, PropertyDescriptor overriddenDescriptor, StackValue field) { - ClassDescriptor toClass = (ClassDescriptor) overriddenDescriptor.getContainingDeclaration(); + public void genDelegate(PropertyDescriptor delegate, PropertyDescriptor overridden, StackValue field) { + ClassDescriptor toClass = (ClassDescriptor) overridden.getContainingDeclaration(); - JvmMethodSignature getterSignature = - typeMapper.mapGetterSignature(declaration.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature(); - functionCodegen.genDelegate(declaration.getGetter(), toClass, field, getterSignature, getterSignature); + functionCodegen.genDelegate(delegate.getGetter(), toClass, field, + typeMapper.mapGetterSignature(delegate, OwnerKind.IMPLEMENTATION).getJvmMethodSignature(), + typeMapper.mapGetterSignature(overridden.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature()); - if (declaration.isVar()) { - JvmMethodSignature setterSignature = - typeMapper.mapSetterSignature(declaration.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature(); - functionCodegen.genDelegate(declaration.getSetter(), toClass, field, setterSignature, setterSignature); + if (delegate.isVar()) { + functionCodegen.genDelegate(delegate.getSetter(), toClass, field, + typeMapper.mapSetterSignature(delegate, OwnerKind.IMPLEMENTATION).getJvmMethodSignature(), + typeMapper.mapSetterSignature(overridden.getOriginal(), OwnerKind.IMPLEMENTATION).getJvmMethodSignature()); } } } diff --git a/compiler/testData/codegen/bridges/delegation.kt b/compiler/testData/codegen/bridges/delegation.kt new file mode 100644 index 00000000000..41c3ddd3470 --- /dev/null +++ b/compiler/testData/codegen/bridges/delegation.kt @@ -0,0 +1,11 @@ +trait A { + fun foo(): T +} + +class B : A { + override fun foo() = "OK" +} + +class C(a: A) : A by a + +fun box() = (C(B()) : A).foo() diff --git a/compiler/testData/codegen/bridges/delegationProperty.kt b/compiler/testData/codegen/bridges/delegationProperty.kt new file mode 100644 index 00000000000..5ffd4270b87 --- /dev/null +++ b/compiler/testData/codegen/bridges/delegationProperty.kt @@ -0,0 +1,15 @@ +trait A { + var result: T +} + +class B(a: A): A by a + +fun box(): String { + val o = object : A { + override var result = "Fail" + } + val b: A = B(o) + b.result = "OK" + if (b.result != "OK") return "Fail" + return (b : A).result +} diff --git a/compiler/testData/codegen/bridges/substitutionInSuperClassDelegation.kt b/compiler/testData/codegen/bridges/substitutionInSuperClassDelegation.kt new file mode 100644 index 00000000000..d469bf5d7f6 --- /dev/null +++ b/compiler/testData/codegen/bridges/substitutionInSuperClassDelegation.kt @@ -0,0 +1,17 @@ +trait A { + fun id(t: T): T +} + +open class B : A { + override fun id(t: String) = t +} + +class C : B() + +class D : A by C() + +fun box(): String { + val d = D() + if (d.id("") != "") return "Fail" + return (d : A).id("OK") +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/BridgeMethodGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/BridgeMethodGenTest.java index edfa98ced97..465fdf2bc4c 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/BridgeMethodGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/BridgeMethodGenTest.java @@ -30,6 +30,16 @@ public class BridgeMethodGenTest extends CodegenTestCase { blackBoxFile("regressions/kt1959.kt"); } + public void testDelegation() { + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + blackBoxFile("bridges/delegation.kt"); + } + + public void testDelegationProperty() { + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + blackBoxFile("bridges/delegationProperty.kt"); + } + public void testDelegationToTraitImpl() { createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); blackBoxFile("bridges/delegationToTraitImpl.kt"); @@ -95,6 +105,11 @@ public class BridgeMethodGenTest extends CodegenTestCase { blackBoxFile("bridges/substitutionInSuperClass.kt"); } + public void testSubstitutionInSuperClassDelegation() { + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + blackBoxFile("bridges/substitutionInSuperClassDelegation.kt"); + } + public void testSubstitutionInSuperClassAbstractFun() { createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); blackBoxFile("bridges/substitutionInSuperClassAbstractFun.kt");