From e86956819648663f2e8641ce35ad79a8d8cd8842 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 9 Oct 2012 15:57:31 +0400 Subject: [PATCH] Generate bridges for property accessors Use existing FunctionCodegen.generateBridgeIfNeeded() on property getters & setters #KT-2920 Fixed --- .../jet/codegen/PropertyCodegen.java | 42 ++++++++----------- .../bridges/propertyAccessorsWithoutBody.kt | 15 +++++++ .../codegen/bridges/propertyDiamond.kt | 18 ++++++++ .../codegen/bridges/propertySetter.kt | 13 ++++++ .../substitutionInSuperClassProperty.kt | 12 ++++++ .../testData/codegen/regressions/kt2920.kt | 9 ++++ .../jet/codegen/BridgeMethodGenTest.java | 25 +++++++++++ 7 files changed, 110 insertions(+), 24 deletions(-) create mode 100644 compiler/testData/codegen/bridges/propertyAccessorsWithoutBody.kt create mode 100644 compiler/testData/codegen/bridges/propertyDiamond.kt create mode 100644 compiler/testData/codegen/bridges/propertySetter.kt create mode 100644 compiler/testData/codegen/bridges/substitutionInSuperClassProperty.kt create mode 100644 compiler/testData/codegen/regressions/kt2920.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index 70ba8603ee0..0baf3ce6c88 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -53,12 +53,14 @@ import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; public class PropertyCodegen extends GenerationStateAware { private final FunctionCodegen functionCodegen; private final ClassBuilder v; + private final CodegenContext context; private final OwnerKind kind; public PropertyCodegen(CodegenContext context, ClassBuilder v, FunctionCodegen functionCodegen) { super(functionCodegen.getState()); this.v = v; this.functionCodegen = functionCodegen; + this.context = context; this.kind = context.getContextKind(); } @@ -119,20 +121,17 @@ public class PropertyCodegen extends GenerationStateAware { } private void generateGetter(JetProperty p, PropertyDescriptor propertyDescriptor) { - final JetPropertyAccessor getter = p.getGetter(); - if (getter != null) { - if (getter.getBodyExpression() != null) { - JvmPropertyAccessorSignature signature = - typeMapper.mapGetterSignature(propertyDescriptor, kind); - functionCodegen.generateMethod(getter, signature.getJvmMethodSignature(), true, signature.getPropertyTypeKotlinSignature(), - propertyDescriptor.getGetter()); - } - else if (isExternallyAccessible(propertyDescriptor)) { - generateDefaultGetter(p); - } + JetPropertyAccessor getter = p.getGetter(); + if (getter != null && getter.getBodyExpression() != null) { + JvmPropertyAccessorSignature signature = typeMapper.mapGetterSignature(propertyDescriptor, kind); + functionCodegen.generateMethod(getter, signature.getJvmMethodSignature(), true, signature.getPropertyTypeKotlinSignature(), + propertyDescriptor.getGetter()); } else if (isExternallyAccessible(propertyDescriptor)) { generateDefaultGetter(p); + JvmPropertyAccessorSignature signature = typeMapper.mapGetterSignature(propertyDescriptor, kind); + FunctionCodegen.generateBridgeIfNeeded(context, state, v, signature.getJvmMethodSignature().getAsmMethod(), + propertyDescriptor.getGetter(), kind); } } @@ -142,22 +141,17 @@ public class PropertyCodegen extends GenerationStateAware { } private void generateSetter(JetProperty p, PropertyDescriptor propertyDescriptor) { - final JetPropertyAccessor setter = p.getSetter(); - if (setter != null) { - if (setter.getBodyExpression() != null) { - final PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter(); - assert setterDescriptor != null; - JvmPropertyAccessorSignature signature = - typeMapper.mapSetterSignature(propertyDescriptor, kind); - functionCodegen.generateMethod(setter, signature.getJvmMethodSignature(), true, signature.getPropertyTypeKotlinSignature(), - setterDescriptor); - } - else if (isExternallyAccessible(propertyDescriptor)) { - generateDefaultSetter(p); - } + JetPropertyAccessor setter = p.getSetter(); + if (setter != null && setter.getBodyExpression() != null) { + JvmPropertyAccessorSignature signature = typeMapper.mapSetterSignature(propertyDescriptor, kind); + functionCodegen.generateMethod(setter, signature.getJvmMethodSignature(), true, signature.getPropertyTypeKotlinSignature(), + propertyDescriptor.getSetter()); } else if (isExternallyAccessible(propertyDescriptor) && propertyDescriptor.isVar()) { generateDefaultSetter(p); + JvmPropertyAccessorSignature signature = typeMapper.mapSetterSignature(propertyDescriptor, kind); + FunctionCodegen.generateBridgeIfNeeded(context, state, v, signature.getJvmMethodSignature().getAsmMethod(), + propertyDescriptor.getSetter(), kind); } } diff --git a/compiler/testData/codegen/bridges/propertyAccessorsWithoutBody.kt b/compiler/testData/codegen/bridges/propertyAccessorsWithoutBody.kt new file mode 100644 index 00000000000..82a9b0b930c --- /dev/null +++ b/compiler/testData/codegen/bridges/propertyAccessorsWithoutBody.kt @@ -0,0 +1,15 @@ +open class A { + open var x: T = "Fail" as T + get +} + +class B : A() { + override var x: String = "Fail" + set +} + +fun box(): String { + val a: A = B() + a.x = "OK" + return a.x +} diff --git a/compiler/testData/codegen/bridges/propertyDiamond.kt b/compiler/testData/codegen/bridges/propertyDiamond.kt new file mode 100644 index 00000000000..5f8a54a1588 --- /dev/null +++ b/compiler/testData/codegen/bridges/propertyDiamond.kt @@ -0,0 +1,18 @@ +trait A { + val o: O + val k: K +} + +trait B : A + +trait C : A + +class D : B, C { + override val o = "O" + override val k = "K" +} + +fun box(): String { + val a: A = D() + return a.o + a.k +} diff --git a/compiler/testData/codegen/bridges/propertySetter.kt b/compiler/testData/codegen/bridges/propertySetter.kt new file mode 100644 index 00000000000..b26bed9f0fb --- /dev/null +++ b/compiler/testData/codegen/bridges/propertySetter.kt @@ -0,0 +1,13 @@ +trait A { + var v: T +} + +class B : A { + override var v: String = "Fail" +} + +fun box(): String { + val a: A = B() + a.v = "OK" + return a.v +} diff --git a/compiler/testData/codegen/bridges/substitutionInSuperClassProperty.kt b/compiler/testData/codegen/bridges/substitutionInSuperClassProperty.kt new file mode 100644 index 00000000000..ff9dc1f5906 --- /dev/null +++ b/compiler/testData/codegen/bridges/substitutionInSuperClassProperty.kt @@ -0,0 +1,12 @@ +open class A(val t: T) { + open val foo: T = t +} + +open class B : A("Fail") + +class Z : B() { + override val foo = "OK" +} + + +fun box() = (Z() : A).foo diff --git a/compiler/testData/codegen/regressions/kt2920.kt b/compiler/testData/codegen/regressions/kt2920.kt new file mode 100644 index 00000000000..07802cbaad3 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt2920.kt @@ -0,0 +1,9 @@ +trait Tr { + val v: T +} + +class C : Tr { + override val v = "OK" +} + +fun box() = C().v diff --git a/compiler/tests/org/jetbrains/jet/codegen/BridgeMethodGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/BridgeMethodGenTest.java index 0777d4afc29..f42e8385f48 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/BridgeMethodGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/BridgeMethodGenTest.java @@ -149,4 +149,29 @@ public class BridgeMethodGenTest extends CodegenTestCase { createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); blackBoxFile("regressions/kt2702.kt"); } + + public void testKt2920() { + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + blackBoxFile("regressions/kt2920.kt"); + } + + public void testSubstitutionInSuperClassProperty() { + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + blackBoxFile("bridges/substitutionInSuperClassProperty.kt"); + } + + public void testPropertySetter() { + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + blackBoxFile("bridges/propertySetter.kt"); + } + + public void testPropertyDiamond() { + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + blackBoxFile("bridges/propertyDiamond.kt"); + } + + public void testPropertyAccessorsWithoutBody() { + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + blackBoxFile("bridges/propertyAccessorsWithoutBody.kt"); + } }