diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java index 4e2ea6c504e..8e525da0a78 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java @@ -1249,19 +1249,17 @@ public abstract class StackValue { ) { CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); - ReceiverParameterDescriptor dispatchReceiver = descriptor.getDispatchReceiverParameter(); + Type dispatchReceiverType = smartDispatchReceiverType(descriptor, typeMapper); ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter(); if (extensionReceiver != null) { return callableMethod != null ? callableMethod.getExtensionReceiverType() : typeMapper.mapType(extensionReceiver.getType()); } - else if (dispatchReceiver != null) { + else if (dispatchReceiverType != null) { if (AnnotationsPackage.isPlatformStaticInObjectOrClass(descriptor)) { return Type.VOID_TYPE; } - else { - return callableMethod != null ? callableMethod.getDispatchReceiverType() : typeMapper.mapType(dispatchReceiver.getType()); - } + return callableMethod != null ? callableMethod.getDispatchReceiverType() : dispatchReceiverType; } else if (isLocalFunCall(callableMethod)) { return callableMethod.getGenerateCalleeType(); @@ -1270,6 +1268,22 @@ public abstract class StackValue { return Type.VOID_TYPE; } + /** + * Extracts the receiver from the resolved call, workarounding the fact that ResolvedCall#dispatchReceiver doesn't have + * all the needed information, for example there's no way to find out whether or not a smart cast was applied to the receiver. + */ + @Nullable + private static Type smartDispatchReceiverType(@NotNull CallableDescriptor descriptor, @NotNull JetTypeMapper typeMapper) { + ReceiverParameterDescriptor dispatchReceiverParameter = descriptor.getDispatchReceiverParameter(); + if (dispatchReceiverParameter == null) return null; + + DeclarationDescriptor container = descriptor.getContainingDeclaration(); + if (container instanceof ClassDescriptor) { + return typeMapper.mapClass((ClassDescriptor) container); + } + + return typeMapper.mapType(dispatchReceiverParameter); + } @Override public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { diff --git a/compiler/testData/codegen/box/classes/diamondInheritance.kt b/compiler/testData/codegen/box/classes/diamondInheritance.kt deleted file mode 100644 index f20f33ab2cd..00000000000 --- a/compiler/testData/codegen/box/classes/diamondInheritance.kt +++ /dev/null @@ -1,24 +0,0 @@ -// Changed when traits were introduced. May not make sense any more - -open class Base() { - public var v : Int = 0 -} - -open class Left() : Base() {} -interface Right : Base {} - -class D() : Left(), Right - -fun vl(l : Left) : Int = l.v -fun vr(r : Right) : Int = r.v - -fun box() : String { - val d = D() - d.v = 42 - - if (d.v != 42) return "Fail #1" - if (vl(d) != 42) return "Fail #2" - if (vr(d) != 42) return "Fail #3" - - return "OK" -} diff --git a/compiler/testData/codegen/box/properties/kt3930.kt b/compiler/testData/codegen/box/properties/kt3930.kt new file mode 100644 index 00000000000..b03168b7f43 --- /dev/null +++ b/compiler/testData/codegen/box/properties/kt3930.kt @@ -0,0 +1,16 @@ +public abstract class Foo { + var isOpen = true + private set +} +public class Bar: Foo() { + inner class Baz { + fun call() { + val s = this@Bar + s.isOpen + } + } +} +fun box(): String { + Bar().Baz() + return "OK" +} diff --git a/compiler/testData/codegen/box/traits/diamondPropertyAccessors.kt b/compiler/testData/codegen/box/traits/diamondPropertyAccessors.kt new file mode 100644 index 00000000000..e1c4d7a6b36 --- /dev/null +++ b/compiler/testData/codegen/box/traits/diamondPropertyAccessors.kt @@ -0,0 +1,23 @@ +interface A { + var bar: Boolean + get() = false + set(value) { throw AssertionError("Fail set") } +} + +interface B : A + +interface C : A { + override var bar: Boolean + get() = true + set(value) {} +} + +interface D : B, C + +class Impl : D + +fun box(): String { + Impl().bar = false + if (!Impl().bar) return "Fail get" + return "OK" +} diff --git a/compiler/testData/codegen/box/traits/indirectlyInheritPropertyGetter.kt b/compiler/testData/codegen/box/traits/indirectlyInheritPropertyGetter.kt new file mode 100644 index 00000000000..75cde1daa46 --- /dev/null +++ b/compiler/testData/codegen/box/traits/indirectlyInheritPropertyGetter.kt @@ -0,0 +1,10 @@ +interface A { + val str: String + get() = "OK" +} + +interface B : A + +class Impl : B + +fun box() = Impl().str diff --git a/compiler/testData/codegen/boxWithJava/properties/substituteJavaSuperField/Test.java b/compiler/testData/codegen/boxWithJava/properties/substituteJavaSuperField/Test.java new file mode 100644 index 00000000000..000dc4e1080 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/properties/substituteJavaSuperField/Test.java @@ -0,0 +1,3 @@ +abstract class Test { + protected final F value = null; +} diff --git a/compiler/testData/codegen/boxWithJava/properties/substituteJavaSuperField/substituteJavaSuperField.kt b/compiler/testData/codegen/boxWithJava/properties/substituteJavaSuperField/substituteJavaSuperField.kt new file mode 100644 index 00000000000..37b781bab5b --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/properties/substituteJavaSuperField/substituteJavaSuperField.kt @@ -0,0 +1,7 @@ +class A : Test() { + fun foo(): String? = value +} + +fun box(): String { + return if (A().foo() == null) "OK" else "Fail" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java index 788e123df67..9e20827179e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -1030,12 +1030,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } - @TestMetadata("diamondInheritance.kt") - public void testDiamondInheritance() throws Exception { - String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/diamondInheritance.kt"); - doTest(fileName); - } - @TestMetadata("exceptionConstructor.kt") public void testExceptionConstructor() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/exceptionConstructor.kt"); @@ -6130,6 +6124,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("kt3930.kt") + public void testKt3930() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/properties/kt3930.kt"); + doTest(fileName); + } + @TestMetadata("kt4140.kt") public void testKt4140() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/properties/kt4140.kt"); @@ -6967,6 +6967,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/traits"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("diamondPropertyAccessors.kt") + public void testDiamondPropertyAccessors() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/diamondPropertyAccessors.kt"); + doTest(fileName); + } + @TestMetadata("finalMethod.kt") public void testFinalMethod() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/finalMethod.kt"); @@ -6979,6 +6985,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("indirectlyInheritPropertyGetter.kt") + public void testIndirectlyInheritPropertyGetter() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/indirectlyInheritPropertyGetter.kt"); + doTest(fileName); + } + @TestMetadata("inheritedFun.kt") public void testInheritedFun() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/inheritedFun.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java index 0d59069e2e2..1b873ebae00 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java @@ -241,6 +241,12 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege doTestWithJava(fileName); } + @TestMetadata("substituteJavaSuperField") + public void testSubstituteJavaSuperField() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/properties/substituteJavaSuperField/"); + doTestWithJava(fileName); + } + } @TestMetadata("compiler/testData/codegen/boxWithJava/reflection") diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java index 1f667d97f40..b03a1c84f8b 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/PropertyDescriptorImpl.java @@ -244,7 +244,7 @@ public class PropertyDescriptorImpl extends VariableDescriptorImpl implements Pr PropertyGetterDescriptorImpl newGetter = getter == null ? null : new PropertyGetterDescriptorImpl( substitutedDescriptor, getter.getAnnotations(), newModality, convertVisibility(getter.getVisibility(), newVisibility), - getter.hasBody(), getter.isDefault(), kind, getter.getOriginal(), SourceElement.NO_SOURCE + getter.hasBody(), getter.isDefault(), kind, original == null ? null : original.getGetter(), SourceElement.NO_SOURCE ); if (newGetter != null) { JetType returnType = getter.getReturnType(); @@ -252,7 +252,7 @@ public class PropertyDescriptorImpl extends VariableDescriptorImpl implements Pr } PropertySetterDescriptorImpl newSetter = setter == null ? null : new PropertySetterDescriptorImpl( substitutedDescriptor, setter.getAnnotations(), newModality, convertVisibility(setter.getVisibility(), newVisibility), - setter.hasBody(), setter.isDefault(), kind, setter.getOriginal(), SourceElement.NO_SOURCE + setter.hasBody(), setter.isDefault(), kind, original == null ? null : original.getSetter(), SourceElement.NO_SOURCE ); if (newSetter != null) { List substitutedValueParameters = FunctionDescriptorImpl.getSubstitutedValueParameters(newSetter, setter, substitutor);