diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 7f2a24472aa..9d1f194b782 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -2595,7 +2595,7 @@ public class ExpressionCodegen extends KtVisitor impleme if (!skipPropertyAccessors) { if (!couldUseDirectAccessToProperty(propertyDescriptor, true, isDelegatedProperty, context, state.getShouldInlineConstVals())) { - propertyDescriptor = context.getAccessorForSuperCallIfNeeded(propertyDescriptor, superCallTarget); + propertyDescriptor = context.getAccessorForSuperCallIfNeeded(propertyDescriptor, superCallTarget, state); propertyDescriptor = context.accessibleDescriptor(propertyDescriptor, superCallTarget); @@ -2765,7 +2765,7 @@ public class ExpressionCodegen extends KtVisitor impleme FunctionDescriptor fd = accessibleFunctionDescriptor(resolvedCall); ClassDescriptor superCallTarget = getSuperCallTarget(call); - fd = context.getAccessorForSuperCallIfNeeded(fd, superCallTarget); + fd = context.getAccessorForSuperCallIfNeeded(fd, superCallTarget, state); Collection codegenExtensions = ExpressionCodegenExtension.Companion.getInstances(state.getProject()); if (!codegenExtensions.isEmpty()) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java index 90cc207da6c..5164433153f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor; +import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor; import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor; import org.jetbrains.kotlin.load.kotlin.*; import org.jetbrains.kotlin.psi.Call; @@ -98,6 +99,17 @@ public class JvmCodegenUtil { return isJvm8InterfaceWithDefaults(declaration, state); } + public static boolean isNonDefaultInterfaceMember(@NotNull CallableMemberDescriptor descriptor, @NotNull GenerationState state) { + if (!isJvmInterface(descriptor.getContainingDeclaration())) { + return false; + } + if (descriptor instanceof JavaCallableMemberDescriptor) { + return descriptor.getModality() == Modality.ABSTRACT; + } + + return !isJvm8InterfaceWithDefaultsMember(descriptor, state); + } + public static boolean isJvmInterface(DeclarationDescriptor descriptor) { if (descriptor instanceof ClassDescriptor) { ClassKind kind = ((ClassDescriptor) descriptor).getKind(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 2f5817ae33c..a069023f826 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -67,6 +67,7 @@ import java.util.*; import static org.jetbrains.kotlin.codegen.AsmUtil.*; import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvm8InterfaceWithDefaultsMember; +import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isNonDefaultInterfaceMember; import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED; import static org.jetbrains.kotlin.resolve.BindingContext.*; import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; @@ -771,7 +772,7 @@ public abstract class MemberCodegen { @SuppressWarnings("unchecked") @NotNull - public D getAccessorForSuperCallIfNeeded(@NotNull D descriptor, @Nullable ClassDescriptor superCallTarget) { - if (superCallTarget != null && !isJvmInterface(descriptor.getContainingDeclaration())) { + public D getAccessorForSuperCallIfNeeded( + @NotNull D descriptor, + @Nullable ClassDescriptor superCallTarget, + @NotNull GenerationState state) { + if (superCallTarget != null && !isNonDefaultInterfaceMember(descriptor, state)) { CodegenContext afterInline = getFirstCrossInlineOrNonInlineContext(); CodegenContext c = afterInline.findParentContextWithDescriptor(superCallTarget); assert c != null : "Couldn't find a context for a super-call: " + descriptor; diff --git a/compiler/testData/codegen/java8/box/capturedSuperCall.kt b/compiler/testData/codegen/java8/box/capturedSuperCall.kt new file mode 100644 index 00000000000..78dfc58c5e3 --- /dev/null +++ b/compiler/testData/codegen/java8/box/capturedSuperCall.kt @@ -0,0 +1,28 @@ +// FILE: IBase.java + +interface IBase { + default String bar() { + return "OK"; + } +} + +// FILE: Kotlin.kt +open class Base { + fun foo() = "OK" +} + +class C : Base(), IBase { + val lambda1 = { + super.foo() + } + + val lambda2 = { + super.bar() + } +} + +fun box(): String { + if (C().lambda1() != "OK") return "fail 1" + + return C().lambda2() +} diff --git a/compiler/testData/codegen/java8/box/jvm8/capturedSuperCall.kt b/compiler/testData/codegen/java8/box/jvm8/capturedSuperCall.kt new file mode 100644 index 00000000000..b02ad946e34 --- /dev/null +++ b/compiler/testData/codegen/java8/box/jvm8/capturedSuperCall.kt @@ -0,0 +1,29 @@ +// JVM_TARGET: 1.8 +// FILE: IBase.java + +interface IBase { + default String bar() { + return "OK"; + } +} + +// FILE: Kotlin.kt +open class Base { + fun foo() = "OK" +} + +class C : Base(), IBase { + val lambda1 = { + super.foo() + } + + val lambda2 = { + super.bar() + } +} + +fun box(): String { + if (C().lambda1() != "OK") return "fail 1" + + return C().lambda2() +} diff --git a/compiler/testData/codegen/java8/box/jvm8/defaults/capturedSuperCall.kt b/compiler/testData/codegen/java8/box/jvm8/defaults/capturedSuperCall.kt new file mode 100644 index 00000000000..6dfab89d205 --- /dev/null +++ b/compiler/testData/codegen/java8/box/jvm8/defaults/capturedSuperCall.kt @@ -0,0 +1,26 @@ +// JVM_TARGET: 1.8 +// KOTLIN_CONFIGURATION_FLAGS: +JVM.JVM8_TARGET_WITH_DEFAULTS + +interface IBase { + fun bar() = "OK" +} + +open class Base { + fun foo() = "OK" +} + +class C : Base(), IBase { + val lambda1 = { + super.foo() + } + + val lambda2 = { + super.bar() + } +} + +fun box(): String { + if (C().lambda1() != "OK") return "fail 1" + + return C().lambda2() +} diff --git a/compiler/tests-java8/tests/org/jetbrains/kotlin/codegen/BlackBoxWithJava8CodegenTestGenerated.java b/compiler/tests-java8/tests/org/jetbrains/kotlin/codegen/BlackBoxWithJava8CodegenTestGenerated.java index f9095baf946..63364a783bd 100644 --- a/compiler/tests-java8/tests/org/jetbrains/kotlin/codegen/BlackBoxWithJava8CodegenTestGenerated.java +++ b/compiler/tests-java8/tests/org/jetbrains/kotlin/codegen/BlackBoxWithJava8CodegenTestGenerated.java @@ -48,6 +48,12 @@ public class BlackBoxWithJava8CodegenTestGenerated extends AbstractBlackBoxCodeg doTest(fileName); } + @TestMetadata("capturedSuperCall.kt") + public void testCapturedSuperCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/capturedSuperCall.kt"); + doTest(fileName); + } + @TestMetadata("defaultMethodCallFromInterface.kt") public void testDefaultMethodCallFromInterface() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/defaultMethodCallFromInterface.kt"); @@ -197,6 +203,12 @@ public class BlackBoxWithJava8CodegenTestGenerated extends AbstractBlackBoxCodeg doTest(fileName); } + @TestMetadata("capturedSuperCall.kt") + public void testCapturedSuperCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/jvm8/capturedSuperCall.kt"); + doTest(fileName); + } + @TestMetadata("defaultArgs.kt") public void testDefaultArgs() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/jvm8/defaultArgs.kt"); @@ -283,6 +295,12 @@ public class BlackBoxWithJava8CodegenTestGenerated extends AbstractBlackBoxCodeg doTest(fileName); } + @TestMetadata("capturedSuperCall.kt") + public void testCapturedSuperCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/jvm8/defaults/capturedSuperCall.kt"); + doTest(fileName); + } + @TestMetadata("defaultArgs.kt") public void testDefaultArgs() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/jvm8/defaults/defaultArgs.kt");