From d1c2862e2722bc4e81e7f044c2bedac8c2ba2941 Mon Sep 17 00:00:00 2001 From: Kristoffer Andersen Date: Tue, 5 Nov 2019 15:37:43 +0100 Subject: [PATCH] IR: Align Interface Defaults with Old Backend Change the treatment of default implementations on interfaces in JVM compatibility mode. Previously, the IR backend moved the actual default implementation to the DefaultImpls class, and then bridged to it from the interface default. The old backend did the reverse, at the cost of an additional accessor, in order to gain better binary compatibility properties. See #2612 for discussion. The accessor needs to call a specific implementation, so must be performed through an `invokespecial`. We trick the SyntheticAccessorLowering into doing this for us, by marking the bridging call as a super call. We do this in want of an explicit `invokespecial` Ir Node. InterfaceDefaultCallsPhase previously assumed the old behaviour of the IR backend (that calls to default implementations, e.g. `foo$default` should target `DefaultImpls.foo$default`). But now the bridge to foo$default resides on `DefaultImpls` already, causing that pass to create a recursive loop. We cut that loop with a simple check. --- .../jvm/lower/InterfaceDelegationLowering.kt | 9 +- .../backend/jvm/lower/InterfaceLowering.kt | 100 +++++++++++------- .../jvm/lower/SyntheticAccessorLowering.kt | 77 +++++++------- .../compatibility/interfaceExtension.kt | 11 ++ .../jvmDefault/compatibility/defaultArgs.kt | 3 +- .../jvmDefault/compatibility/simpleDiamond.kt | 22 ++++ .../compatibility/simpleFunction.kt | 5 +- .../simpleFunctionWithAbstractOverride.kt | 13 ++- .../compatibility/simpleProperty.kt | 9 +- .../codegen/BlackBoxCodegenTestGenerated.java | 5 + .../codegen/BytecodeTextTestGenerated.java | 5 + .../LightAnalysisModeTestGenerated.java | 5 + .../ir/FirBlackBoxCodegenTestGenerated.java | 5 + .../ir/IrBlackBoxCodegenTestGenerated.java | 5 + .../ir/IrBytecodeTextTestGenerated.java | 5 + 15 files changed, 187 insertions(+), 92 deletions(-) create mode 100644 compiler/testData/codegen/box/jvm8/defaults/compatibility/interfaceExtension.kt create mode 100644 compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleDiamond.kt diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt index b392925cc33..e76713c2da3 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceDelegationLowering.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom import org.jetbrains.kotlin.backend.common.lower.createIrBuilder @@ -164,7 +165,7 @@ internal val interfaceDefaultCallsPhase = makeIrFilePhase( description = "Redirect interface calls with default arguments to DefaultImpls" ) -private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), FileLoweringPass { +private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass { // TODO If there are no default _implementations_ we can avoid generating defaultImpls class entirely by moving default arg dispatchers to the interface class override fun lower(irFile: IrFile) { irFile.transformChildrenVoid(this) @@ -181,6 +182,12 @@ private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : Ir } val redirectTarget = context.declarationFactory.getDefaultImplsFunction(callee as IrSimpleFunction) + + // InterfaceLowering bridges from DefaultImpls in compatibility mode -- if that's the case, + // this phase will inadvertently cause a recursive loop as the bridge on the DefaultImpls + // gets redirected to call itself. + if (redirectTarget == currentFunction?.irElement) return super.visitCall(expression) + val newCall = irCall(expression, redirectTarget, receiversAsArguments = true) return super.visitCall(newCall) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt index f0e580b1df2..7673f286d88 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InterfaceLowering.kt @@ -9,7 +9,6 @@ import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.ir.copyBodyToStatic import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom -import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface @@ -17,10 +16,6 @@ import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET -import org.jetbrains.kotlin.ir.builders.irBlockBody -import org.jetbrains.kotlin.ir.builders.irExprBody -import org.jetbrains.kotlin.ir.builders.irReturn import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* @@ -74,7 +69,12 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran /** * 2) They inherit a default implementation from an interface this interface - * extends: create a bridge from companion to companion, if necessary: + * extends: create a bridge from companion to companion, unless + * - the implementation is private or belongs to java.lang.Object + * - we're in JVM Compatibility Default mode, in which case we go via + * accessors on the parent class rather than the DefaultImpls + * - we're in JVM Default mode, and we have that default implementation, + * in which case we simply leave it. * * ``` * interface A { fun foo() = 0 } @@ -91,11 +91,20 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran function.origin == IrDeclarationOrigin.FAKE_OVERRIDE -> { val implementation = function.resolveFakeOverride()!! - if (!Visibilities.isPrivate(implementation.visibility) - && !implementation.isMethodOfAny() - && (!implementation.hasJvmDefault() || context.state.jvmDefaultMode.isCompatibility) - ) { - delegateInheritedDefaultImplementationToDefaultImpls(function, implementation) + when { + Visibilities.isPrivate(implementation.visibility) || implementation.isMethodOfAny() -> + continue@loop + context.state.jvmDefaultMode.isCompatibility -> { + val defaultImpl = createDefaultImpl(function) + defaultImpl.bridgeViaAccessorTo(function) + } + !implementation.hasJvmDefault() -> { + val defaultImpl = createDefaultImpl(function) + context.declarationFactory.getDefaultImplsFunction(implementation).also { + defaultImpl.bridgeToStatic(it) + } + } + // else -> Do nothing. } } @@ -106,7 +115,9 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran Visibilities.isPrivate(function.visibility) || (function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER && !function.hasJvmDefault()) || function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS -> { - removedFunctions[function.symbol] = createDefaultImpl(function).symbol + val defaultImpl = createDefaultImpl(function) + function.copyImplementationTo(defaultImpl) + removedFunctions[function.symbol] = defaultImpl.symbol } /** @@ -114,7 +125,8 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran * an abstract stub is left. */ !function.hasJvmDefault() -> { - createDefaultImpl(function) + val defaultImpl = createDefaultImpl(function) + function.copyImplementationTo(defaultImpl) function.body = null //TODO reset modality to abstract } @@ -124,7 +136,7 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran */ context.state.jvmDefaultMode.isCompatibility -> { val defaultImpl = createDefaultImpl(function) - function.body = createDelegatingCall(defaultImpl, function) + defaultImpl.bridgeViaAccessorTo(function) } // 6) ... otherwise we simply leave the default function implementation on the interface. @@ -163,40 +175,52 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran } private fun createDefaultImpl(function: IrSimpleFunction): IrSimpleFunction = - context.declarationFactory.getDefaultImplsFunction(function).also { newFunction -> + context.declarationFactory.getDefaultImplsFunction(function).also {newFunction -> newFunction.body = function.body?.patchDeclarationParents(newFunction) - copyBodyToStatic(function, newFunction) newFunction.parentAsClass.declarations.add(newFunction) } - private fun createDelegatingCall(defaultImpls: IrFunction, interfaceMethod: IrFunction): IrExpressionBody { - val startOffset = interfaceMethod.startOffset - val endOffset = interfaceMethod.endOffset + private fun IrSimpleFunction.copyImplementationTo(target: IrSimpleFunction) { + copyBodyToStatic(this, target) + } - return IrExpressionBodyImpl(IrCallImpl(startOffset, endOffset, interfaceMethod.returnType, defaultImpls.symbol).apply { - passTypeArgumentsFrom(interfaceMethod) - - var offset = 0 - interfaceMethod.dispatchReceiverParameter?.let { - putValueArgument(offset++, IrGetValueImpl(startOffset, endOffset, it.symbol)) - } - interfaceMethod.extensionReceiverParameter?.let { - putValueArgument(offset++, IrGetValueImpl(startOffset, endOffset, it.symbol)) - } - interfaceMethod.valueParameters.forEachIndexed { i, it -> - putValueArgument(i + offset, IrGetValueImpl(startOffset, endOffset, it.symbol)) + // Bridge from static to static method - simply fill the arguments to the parameters. + // By nature of the generation of both source and target of bridge, they line up. + private fun IrFunction.bridgeToStatic(callTarget: IrFunction) { + body = IrExpressionBodyImpl(IrCallImpl(startOffset, endOffset, returnType, callTarget.symbol).also { call -> + call.passTypeArgumentsFrom(this) + valueParameters.forEachIndexed { i, it -> + call.putValueArgument(i, IrGetValueImpl(startOffset, endOffset, it.symbol)) } }) } - private fun delegateInheritedDefaultImplementationToDefaultImpls(fakeOverride: IrSimpleFunction, implementation: IrSimpleFunction) { - val defaultImplFun = context.declarationFactory.getDefaultImplsFunction(implementation) - val irFunction = context.declarationFactory.getDefaultImplsFunction(fakeOverride) + // Bridge from static DefaultImpl method to the interface method. Arguments need to + // be shifted in presence of dispatch and extension receiver. + private fun IrFunction.bridgeViaAccessorTo(callTarget: IrFunction) { + body = IrExpressionBodyImpl( + IrCallImpl( + startOffset, + endOffset, + returnType, + callTarget.symbol, + superQualifierSymbol = callTarget.parentAsClass.symbol + ).also { call -> + call.passTypeArgumentsFrom(this) - irFunction.parentAsClass.declarations.add(irFunction) - context.createIrBuilder(irFunction.symbol, UNDEFINED_OFFSET, UNDEFINED_OFFSET).apply { - irFunction.body = createDelegatingCall(defaultImplFun, irFunction) - } + var offset = 0 + callTarget.dispatchReceiverParameter?.let { + call.dispatchReceiver = IrGetValueImpl(startOffset, endOffset, valueParameters[offset].symbol) + offset += 1 + } + callTarget.extensionReceiverParameter?.let { + call.extensionReceiver = IrGetValueImpl(startOffset, endOffset, valueParameters[offset].symbol) + offset += 1 + } + for (i in offset until valueParameters.size) { + call.putValueArgument(i - 1, IrGetValueImpl(startOffset, endOffset, valueParameters[i].symbol)) + } + }) } override fun visitReturn(expression: IrReturn): IrExpression { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt index b8b0896cc13..d55f4c7f13d 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom import org.jetbrains.kotlin.backend.common.ir.remapTypeParameters import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin +import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface import org.jetbrains.kotlin.backend.jvm.intrinsics.receiverAndArgs import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator import org.jetbrains.kotlin.backend.jvm.ir.isLambda @@ -187,48 +188,52 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle private fun IrSimpleFunction.makeSimpleFunctionAccessor(expression: IrCall): IrSimpleFunction { val source = this + + // Find the right container to insert the accessor. Simply put, when we call a function on a class A, + // we also need to put its accessor into A. However, due to the way that calls are implemented in the + // IR we generally need to look at the type of the dispatchReceiver *argument* in order to find the + // correct class. Consider the following code: + // + // fun run(f : () -> Int): Int = f() + // + // open class A { + // private fun f() = 0 + // fun g() = run { this.f() } + // } + // + // class B : A { + // override fun g() = 1 + // fun h() = run { super.g() } + // } + // + // We have calls to the private methods A.f from a generated Lambda subclass for the argument to `run` + // in class A and a super call to A.g from a generated Lambda subclass in class B. + // + // In the first case, we need to produce an accessor in class A to access the private member of A. + // Both the parent of the function f and the type of the dispatch receiver point to the correct class. + // In the second case we need to call A.g from within class B, since this is the only way to invoke + // a method of a superclass on the JVM. However, the IR for the call to super.g points directly to the + // function g in class A. Confusingly, the `superQualifier` on this call also points to class A. + // The only way to compute the actual enclosing class for the call is by looking at the type of the + // dispatch receiver argument, which points to B. + // + // Beyond this, there can be accessors that are needed because other lowerings produce code calling + // private methods (e.g., local functions for lambdas are private and called from generated + // SAM wrapper classes). In this case we rely on the parent field of the called function. + // + // Finally, we need to produce accessors for calls to protected static methods coming from Java, + // which we put in the closest enclosing class which has access to the method in question. + val dispatchReceiverType = expression.dispatchReceiver?.type + val parent = source.accessorParent(dispatchReceiverType?.classOrNull?.owner ?: source.parent) + return buildFun { origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR name = source.accessorName() visibility = Visibilities.PUBLIC + modality = if (parent is IrClass && parent.isJvmInterface) Modality.OPEN else Modality.FINAL isSuspend = source.isSuspend // synthetic accessors of suspend functions are handled in codegen }.also { accessor -> - // Find the right container to insert the accessor. Simply put, when we call a function on a class A, - // we also need to put its accessor into A. However, due to the way that calls are implemented in the - // IR we generally need to look at the type of the dispatchReceiver *argument* in order to find the - // correct class. Consider the following code: - // - // fun run(f : () -> Int): Int = f() - // - // open class A { - // private fun f() = 0 - // fun g() = run { this.f() } - // } - // - // class B : A { - // override fun g() = 1 - // fun h() = run { super.g() } - // } - // - // We have calls to the private methods A.f from a generated Lambda subclass for the argument to `run` - // in class A and a super call to A.g from a generated Lambda subclass in class B. - // - // In the first case, we need to produce an accessor in class A to access the private member of A. - // Both the parent of the function f and the type of the dispatch receiver point to the correct class. - // In the second case we need to call A.g from within class B, since this is the only way to invoke - // a method of a superclass on the JVM. However, the IR for the call to super.g points directly to the - // function g in class A. Confusingly, the `superQualifier` on this call also points to class A. - // The only way to compute the actual enclosing class for the call is by looking at the type of the - // dispatch receiver argument, which points to B. - // - // Beyond this, there can be accessors that are needed because other lowerings produce code calling - // private methods (e.g., local functions for lambdas are private and called from generated - // SAM wrapper classes). In this case we rely on the parent field of the called function. - // - // Finally, we need to produce accessors for calls to protected static methods coming from Java, - // which we put in the closest enclosing class which has access to the method in question. - val dispatchReceiverType = expression.dispatchReceiver?.type - accessor.parent = source.accessorParent(dispatchReceiverType?.classOrNull?.owner ?: source.parent) + accessor.parent = parent pendingTransformations.add { (accessor.parent as IrDeclarationContainer).declarations.add(accessor) } accessor.copyTypeParametersFrom(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR) diff --git a/compiler/testData/codegen/box/jvm8/defaults/compatibility/interfaceExtension.kt b/compiler/testData/codegen/box/jvm8/defaults/compatibility/interfaceExtension.kt new file mode 100644 index 00000000000..99206085bd7 --- /dev/null +++ b/compiler/testData/codegen/box/jvm8/defaults/compatibility/interfaceExtension.kt @@ -0,0 +1,11 @@ +// !JVM_DEFAULT_MODE: compatibility +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// WITH_RUNTIME +interface A { + @JvmDefault + fun String.foo() = "OK" +} + +fun box(): String = + object : A { fun box() = "FAIL".foo() }.box() diff --git a/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/defaultArgs.kt b/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/defaultArgs.kt index f64de648f40..e135cac740b 100644 --- a/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/defaultArgs.kt +++ b/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/defaultArgs.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: compatibility -// IGNORE_BACKEND: JVM_IR // JVM_TARGET: 1.8 // FULL_JDK @@ -10,7 +9,7 @@ interface KInterface { } } -// 1 INVOKESTATIC KInterface.access\$test\$jd +// 1 INVOKESTATIC KInterface.access\$test\$ // 1 INVOKESTATIC KInterface.test\$default // from $default diff --git a/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleDiamond.kt b/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleDiamond.kt new file mode 100644 index 00000000000..e95fd1936d1 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleDiamond.kt @@ -0,0 +1,22 @@ +// !JVM_DEFAULT_MODE: compatibility +// JVM_TARGET: 1.8 + +interface A { + @JvmDefault + fun foo() = "FAIL" +} + +interface Left : A { } +interface Right : A { + @JvmDefault + override fun foo() = "OK" +} + +interface C : Left, Right {} + +fun box(): String { + val x = object : C {} + return x.foo() +} + +// 0 INVOKESTATIC .*\$DefaultImpls\.foo diff --git a/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleFunction.kt b/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleFunction.kt index 0051b12e7d2..523733c4279 100644 --- a/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleFunction.kt +++ b/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleFunction.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: compatibility -// IGNORE_BACKEND: JVM_IR // JVM_TARGET: 1.8 interface KInterface { @@ -13,8 +12,8 @@ interface KInterface2 : KInterface { } -// 1 INVOKESTATIC KInterface2.access\$test2\$jd -// 1 INVOKESTATIC KInterface.access\$test2\$jd +// 1 INVOKESTATIC KInterface2.access\$test2\$ +// 1 INVOKESTATIC KInterface.access\$test2\$ // 1 INVOKESPECIAL KInterface2.test2 // 1 INVOKESPECIAL KInterface.test2 diff --git a/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleFunctionWithAbstractOverride.kt b/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleFunctionWithAbstractOverride.kt index 904586556ad..32fe14cee28 100644 --- a/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleFunctionWithAbstractOverride.kt +++ b/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleFunctionWithAbstractOverride.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: compatibility -// IGNORE_BACKEND: JVM_IR // JVM_TARGET: 1.8 interface KInterface { @@ -14,11 +13,11 @@ interface KInterface2 : KInterface { abstract override fun test2(): String } -// 1 INVOKESTATIC KInterface.access\$test2\$jd -// + -// 0 INVOKESTATIC KInterface2.access\$test2\$jd -// = -// 1 INVOKESTATIC - // 1 INVOKESPECIAL KInterface.test2 // 0 INVOKESPECIAL KInterface2.test2 + +// 1 INVOKESTATIC KInterface.access\$test2\$ +// + +// 0 INVOKESTATIC KInterface2.access\$test2\$ +// = +// 1 INVOKESTATIC KInterface \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleProperty.kt b/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleProperty.kt index b7e0f1c6654..673e8c8e188 100644 --- a/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleProperty.kt +++ b/compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleProperty.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: compatibility -// IGNORE_BACKEND: JVM_IR // JVM_TARGET: 1.8 interface KInterface { @@ -14,10 +13,10 @@ interface KInterface2 : KInterface { } -// 1 INVOKESTATIC KInterface2.access\$getBar\$jd -// 1 INVOKESTATIC KInterface2.access\$setBar\$jd -// 1 INVOKESTATIC KInterface.access\$getBar\$jd -// 1 INVOKESTATIC KInterface.access\$setBar\$jd +// 1 INVOKESTATIC KInterface2.access\$getBar\$ +// 1 INVOKESTATIC KInterface2.access\$setBar\$ +// 1 INVOKESTATIC KInterface.access\$getBar\$ +// 1 INVOKESTATIC KInterface.access\$setBar\$ // 1 INVOKESPECIAL KInterface2.getBar // 1 INVOKESPECIAL KInterface2.setBar diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 897b9ac6d2d..2b71472fe73 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -14863,6 +14863,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedJvmDefault.kt"); } + @TestMetadata("interfaceExtension.kt") + public void testInterfaceExtension() throws Exception { + runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/interfaceExtension.kt"); + } + @TestMetadata("propertyAnnotation.kt") public void testPropertyAnnotation() throws Exception { runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/propertyAnnotation.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index b5c2d930766..8da7dba167f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -3002,6 +3002,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/defaultArgs.kt"); } + @TestMetadata("simpleDiamond.kt") + public void testSimpleDiamond() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleDiamond.kt"); + } + @TestMetadata("simpleFunction.kt") public void testSimpleFunction() throws Exception { runTest("compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleFunction.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index bfdd62c684a..4f83826e2e8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -14863,6 +14863,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedJvmDefault.kt"); } + @TestMetadata("interfaceExtension.kt") + public void testInterfaceExtension() throws Exception { + runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/interfaceExtension.kt"); + } + @TestMetadata("propertyAnnotation.kt") public void testPropertyAnnotation() throws Exception { runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/propertyAnnotation.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 0423834c7f6..7de4d0f4831 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -13713,6 +13713,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedJvmDefault.kt"); } + @TestMetadata("interfaceExtension.kt") + public void testInterfaceExtension() throws Exception { + runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/interfaceExtension.kt"); + } + @TestMetadata("propertyAnnotation.kt") public void testPropertyAnnotation() throws Exception { runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/propertyAnnotation.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index bfbe6523be4..31ae43743ce 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -13713,6 +13713,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedJvmDefault.kt"); } + @TestMetadata("interfaceExtension.kt") + public void testInterfaceExtension() throws Exception { + runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/interfaceExtension.kt"); + } + @TestMetadata("propertyAnnotation.kt") public void testPropertyAnnotation() throws Exception { runTest("compiler/testData/codegen/box/jvm8/defaults/compatibility/propertyAnnotation.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java index 46ca9370a50..a593dd570d6 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java @@ -3047,6 +3047,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/defaultArgs.kt"); } + @TestMetadata("simpleDiamond.kt") + public void testSimpleDiamond() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleDiamond.kt"); + } + @TestMetadata("simpleFunction.kt") public void testSimpleFunction() throws Exception { runTest("compiler/testData/codegen/bytecodeText/jvm8/jvmDefault/compatibility/simpleFunction.kt");