diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 91e199248a1..1a798b1201f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -144,6 +144,13 @@ private val defaultArgumentInjectorPhase = makeIrFilePhase( prerequisite = setOf(defaultArgumentStubPhase, callableReferencePhase) ) +private val interfacePhase = makeIrFilePhase( + ::InterfaceLowering, + name = "Interface", + description = "Move default implementations of interface members to DefaultImpls class", + prerequisite = setOf(defaultArgumentInjectorPhase) +) + private val innerClassesPhase = makeIrFilePhase( ::InnerClassesLowering, name = "InnerClasses", @@ -158,6 +165,13 @@ private val returnableBlocksPhase = makeIrFilePhase( prerequisite = setOf(arrayConstructorPhase, assertionPhase) ) +private val syntheticAccessorPhase = makeIrFilePhase( + ::SyntheticAccessorLowering, + name = "SyntheticAccessor", + description = "Introduce synthetic accessors", + prerequisite = setOf(objectClassPhase, staticDefaultFunctionPhase, interfacePhase) +) + @Suppress("Reformat") private val jvmFilePhases = typeAliasAnnotationMethodsPhase then 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 8fe274dccd7..6bfe8d07bca 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 @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase 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.ir.hasJvmDefault import org.jetbrains.kotlin.descriptors.Modality @@ -39,7 +38,6 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.utils.addToStdlib.safeAs -import java.util.function.UnaryOperator internal val interfaceDelegationPhase = makeIrFilePhase( ::InterfaceDelegationLowering, @@ -68,95 +66,80 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl } private fun generateInterfaceMethods(irClass: IrClass) { - val (actualClass, isDefaultImplsGeneration) = if (irClass.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS) { - Pair(irClass.parent as IrClass, true) - } else { - Pair(irClass, false) - } - val toRemove = mutableListOf() - for (function in actualClass.functions.toList()) { // Copy the list, because we are adding new declarations from the loop + for (function in irClass.functions.toList()) { // Copy the list, because we are adding new declarations from the loop if (function.origin !== IrDeclarationOrigin.FAKE_OVERRIDE) continue - // In classes, only generate interface delegation for functions immediately inherited from an interface. + // Only generate interface delegation for functions immediately inherited from an interface. // (Otherwise, delegation will be present in the parent class) - if (!isDefaultImplsGeneration && - function.overriddenSymbols.any { - (!it.owner.parentAsClass.isInterface || it.owner.hasJvmDefault()) && - it.owner.modality != Modality.ABSTRACT - } - ) { + if (function.overriddenSymbols.any { !it.owner.parentAsClass.isInterface && it.owner.modality != Modality.ABSTRACT }) { continue } val implementation = function.resolveFakeOverride() ?: continue - if (!implementation.hasInterfaceParent() || - Visibilities.isPrivate(implementation.visibility) || - implementation.isDefinitelyNotDefaultImplsMethod() || - implementation.isMethodOfAny() || - (!context.state.jvmDefaultMode.isCompatibility && implementation.hasJvmDefault()) + + if (!implementation.hasInterfaceParent() + || Visibilities.isPrivate(implementation.visibility) + || implementation.isDefinitelyNotDefaultImplsMethod() + || implementation.isMethodOfAny() + || (!context.state.jvmDefaultMode.isCompatibility && implementation.hasJvmDefault()) ) { continue } - val delegation = generateDelegationToDefaultImpl(irClass, implementation, function, isDefaultImplsGeneration) - if (!isDefaultImplsGeneration) { - toRemove.add(function) - replacementMap[function.symbol] = delegation.symbol - } + toRemove.add(function) + + val delegation = generateDelegationToDefaultImpl(irClass, implementation, function) + irClass.declarations.add(delegation) + replacementMap[function.symbol] = delegation.symbol } irClass.declarations.removeAll(toRemove) } private fun generateDelegationToDefaultImpl( irClass: IrClass, - interfaceFun: IrSimpleFunction, - inheritedFun: IrSimpleFunction, - isDefaultImplsGeneration: Boolean + interfaceImplementation: IrSimpleFunction, + classOverride: IrSimpleFunction ): IrSimpleFunction { - val defaultImplFun = context.declarationFactory.getDefaultImplsFunction(interfaceFun) + val inheritedProperty = classOverride.correspondingPropertySymbol?.owner + val descriptor = DescriptorsToIrRemapper.remapDeclaredSimpleFunction(classOverride.descriptor) val irFunction = - if (!isDefaultImplsGeneration) { - val inheritedProperty = inheritedFun.correspondingPropertySymbol?.owner - val descriptor = DescriptorsToIrRemapper.remapDeclaredSimpleFunction(inheritedFun.descriptor) - IrFunctionImpl( - UNDEFINED_OFFSET, - UNDEFINED_OFFSET, - IrDeclarationOrigin.DEFINED, - IrSimpleFunctionSymbolImpl(descriptor), - inheritedFun.name, - Visibilities.PUBLIC, - inheritedFun.modality, - inheritedFun.returnType, - isInline = inheritedFun.isInline, - isExternal = false, - isTailrec = false, - isSuspend = inheritedFun.isSuspend - ).apply { - descriptor.bind(this) - parent = irClass - overriddenSymbols.addAll(inheritedFun.overriddenSymbols) - copyParameterDeclarationsFrom(inheritedFun) - annotations.addAll(inheritedFun.annotations) + IrFunctionImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + IrDeclarationOrigin.DEFINED, + IrSimpleFunctionSymbolImpl(descriptor), + classOverride.name, + Visibilities.PUBLIC, + classOverride.modality, + classOverride.returnType, + isInline = classOverride.isInline, + isExternal = false, + isTailrec = false, + isSuspend = classOverride.isSuspend + ).apply { + descriptor.bind(this) + parent = irClass + overriddenSymbols.addAll(classOverride.overriddenSymbols) + copyParameterDeclarationsFrom(classOverride) + annotations.addAll(classOverride.annotations) - if (inheritedProperty != null) { - val propertyDescriptor = DescriptorsToIrRemapper.remapDeclaredProperty(inheritedProperty.descriptor) - IrPropertyImpl( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, IrPropertySymbolImpl(propertyDescriptor), - inheritedProperty.name, Visibilities.PUBLIC, inheritedProperty.modality, inheritedProperty.isVar, - inheritedProperty.isConst, inheritedProperty.isLateinit, inheritedProperty.isDelegated, isExternal = false - ).apply { - propertyDescriptor.bind(this) - parent = irClass - correspondingPropertySymbol = symbol - } + if (inheritedProperty != null) { + val propertyDescriptor = DescriptorsToIrRemapper.remapDeclaredProperty(inheritedProperty.descriptor) + IrPropertyImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, IrPropertySymbolImpl(propertyDescriptor), + inheritedProperty.name, Visibilities.PUBLIC, inheritedProperty.modality, inheritedProperty.isVar, + inheritedProperty.isConst, inheritedProperty.isLateinit, inheritedProperty.isDelegated, isExternal = false + ).apply { + propertyDescriptor.bind(this) + parent = irClass + correspondingPropertySymbol = symbol } } - } else context.declarationFactory.getDefaultImplsFunction(inheritedFun) - - irClass.declarations.add(irFunction) + } + val defaultImplFun = context.declarationFactory.getDefaultImplsFunction(interfaceImplementation) context.createIrBuilder(irFunction.symbol, UNDEFINED_OFFSET, UNDEFINED_OFFSET).apply { irFunction.body = irBlockBody { +irReturn( @@ -182,7 +165,7 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl } override fun visitSimpleFunction(declaration: IrSimpleFunction) { - declaration.overriddenSymbols.replaceAll(UnaryOperator { symbol -> replacementMap[symbol] ?: symbol }) + declaration.overriddenSymbols.replaceAll { symbol -> replacementMap[symbol] ?: symbol } super.visitSimpleFunction(declaration) } } @@ -234,7 +217,8 @@ private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : Ir val callee = expression.symbol.owner if (callee.parent.safeAs()?.isInterface != true || - callee.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER + callee.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || + (callee.hasJvmDefault() && !context.state.jvmDefaultMode.isCompatibility) ) { return super.visitCall(expression) } 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 48de8e6f727..bc5bef6200e 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 @@ -7,14 +7,17 @@ package org.jetbrains.kotlin.backend.jvm.lower 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.InitializersLowering.Companion.clinitName -import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase +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.ir.hasJvmDefault 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.irReturn import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression @@ -23,62 +26,95 @@ import org.jetbrains.kotlin.ir.expressions.IrReturn import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrLocalDelegatedPropertySymbol -import org.jetbrains.kotlin.ir.util.copyTypeAndValueArgumentsFrom -import org.jetbrains.kotlin.ir.util.irCall -import org.jetbrains.kotlin.ir.util.isInterface -import org.jetbrains.kotlin.ir.util.patchDeclarationParents +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -internal val interfacePhase = makeIrFilePhase( - ::InterfaceLowering, - name = "Interface", - description = "Move default implementations of interface members to DefaultImpls class" -) +/** + * This phase moves interface members with default implementations to the + * associated companion DefaultImpls with bridges, as appropriate. It then + * performs a traversal of any other code in this interface and redirects calls + * to the interface to the companion, if functions were moved completely. + */ +internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), ClassLoweringPass { -private class InterfaceLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), ClassLoweringPass { - - val state = context.state - val removedFunctions = hashMapOf() + private val removedFunctions = hashMapOf() override fun lower(irClass: IrClass) { if (!irClass.isInterface) return val defaultImplsIrClass = context.declarationFactory.getDefaultImplsClass(irClass) - //TODO: Don't add DefaultImpls if it's empty. Just like the old backend...? - irClass.declarations.add(defaultImplsIrClass) val members = defaultImplsIrClass.declarations - for (function in irClass.declarations) { - if (function !is IrSimpleFunction) continue + // There are 6 cases for functions on interfaces: + loop@ for (function in irClass.functions) { + when { + /** + * 1) They are plain abstract interface functions, in which case we leave them: + */ + function.modality == Modality.ABSTRACT -> + continue@loop - if (function.modality != Modality.ABSTRACT && function.origin != IrDeclarationOrigin.FAKE_OVERRIDE) { + /** + * 2) They inherit a default implementation from an interface this interface + * extends: create a bridge from companion to companion, if necessary: + * + * ``` + * interface A { fun foo() = 0 } + * interface B : A { } + * ``` + * + * yields + * + * ``` + * interface A { fun foo(); class DefaultImpls { fun foo() = 0 } } // !! by Case 4 !! + * interface B : A { class DefaultImpls { fun foo() = A.DefaultImpls.foo() } } + * ``` + */ + function.origin == IrDeclarationOrigin.FAKE_OVERRIDE -> { + val implementation = function.resolveFakeOverride()!! - if(function.hasJvmDefault() && !context.state.jvmDefaultMode.isCompatibility && !mustMoveToDefaultImpls(function)) continue - - val element = context.declarationFactory.getDefaultImplsFunction(function).also { - if (mustMoveToDefaultImpls(function)) - removedFunctions[function.symbol] = it.symbol + if (!Visibilities.isPrivate(implementation.visibility) + && !implementation.isMethodOfAny() + && (!implementation.hasJvmDefault() || context.state.jvmDefaultMode.isCompatibility) + ) { + delegateInheritedDefaultImplementationToDefaultImpls(function, implementation, defaultImplsIrClass) + } } - members.add(element) - copyBodyToStatic(function, element) - element.body = element.body?.patchDeclarationParents(element) + /** + * 3) Private methods, default parameter dispatchers (without @JvmDefault) + * and $annotation methods are always moved without bridges + */ + Visibilities.isPrivate(function.visibility) + || (function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER && !function.hasJvmDefault()) + || function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS -> { + val defaultImpl = createDefaultImpl(function, members) + removedFunctions[function.symbol] = defaultImpl.symbol + } - if (function.hasJvmDefault() && - function.origin != JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS - ) { - function.body = IrExpressionBodyImpl(callDefaultImpls(element, function)) - } else { + /** + * 4) _Without_ @JvmDefault, the default implementation is moved to DefaultImpls and + * an abstract stub is left. + */ + !function.hasJvmDefault() -> { + createDefaultImpl(function, members) function.body = null //TODO reset modality to abstract } + + /** + * 5) _With_ @JvmDefault, we move and bridge if in compatibility mode, ... + */ + context.state.jvmDefaultMode.isCompatibility -> { + val defaultImpl = createDefaultImpl(function, members) + function.body = IrExpressionBodyImpl(createDelegatingCall(defaultImpl, function)) + } + + // 6) ... otherwise we simply leave the default function implementation on the interface. } } - // Update IrElements (e.g., IrCalls) to point to the new functions. - irClass.transformChildrenVoid(this) - irClass.declarations.removeAll { it is IrFunction && removedFunctions.containsKey(it.symbol) } @@ -99,14 +135,20 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans delegatedPropertyArray.parent = defaultImplsIrClass delegatedPropertyArray.initializer?.patchDeclarationParents(defaultImplsIrClass) } + + if (defaultImplsIrClass.declarations.isNotEmpty()) irClass.declarations.add(defaultImplsIrClass) + // Update IrElements (e.g., IrCalls) to point to the new functions. + irClass.transformChildrenVoid(this) } - private fun mustMoveToDefaultImpls(function: IrFunction): Boolean = - Visibilities.isPrivate(function.visibility) && function.name != clinitName || - function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || - function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS + private fun createDefaultImpl(function: IrSimpleFunction, members: MutableList): IrSimpleFunction = + context.declarationFactory.getDefaultImplsFunction(function).also { + it.body = function.body?.patchDeclarationParents(it) + copyBodyToStatic(function, it) + members.add(it) + } - private fun callDefaultImpls(defaultImpls: IrFunction, interfaceMethod: IrFunction): IrCall { + private fun createDelegatingCall(defaultImpls: IrFunction, interfaceMethod: IrFunction): IrCall { val startOffset = interfaceMethod.startOffset val endOffset = interfaceMethod.endOffset @@ -126,6 +168,22 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans } } + private fun delegateInheritedDefaultImplementationToDefaultImpls( + fakeOverride: IrSimpleFunction, + implementation: IrSimpleFunction, + defaultImpls: IrClass + ) { + val defaultImplFun = context.declarationFactory.getDefaultImplsFunction(implementation) + val irFunction = context.declarationFactory.getDefaultImplsFunction(fakeOverride) + + defaultImpls.declarations.add(irFunction) + context.createIrBuilder(irFunction.symbol, UNDEFINED_OFFSET, UNDEFINED_OFFSET).apply { + irFunction.body = irBlockBody { + +irReturn(createDelegatingCall(defaultImplFun, irFunction)) + } + } + } + override fun visitReturn(expression: IrReturn): IrExpression { val newFunction = removedFunctions[expression.returnTargetSymbol]?.owner return super.visitReturn( 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 2db2d699d5e..b1ceed403ef 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 @@ -36,14 +36,7 @@ import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.name.Name -internal val syntheticAccessorPhase = makeIrFilePhase( - ::SyntheticAccessorLowering, - name = "SyntheticAccessor", - description = "Introduce synthetic accessors", - prerequisite = setOf(objectClassPhase, staticDefaultFunctionPhase) -) - -private class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass { +internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass { private val pendingTransformations = mutableListOf>() private val inlineLambdaToCallSite = mutableMapOf() diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrFunctionImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrFunctionImpl.kt index a4c52ae6097..11b61f28234 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrFunctionImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrFunctionImpl.kt @@ -11,12 +11,10 @@ import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction -import org.jetbrains.kotlin.ir.expressions.IrBody import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.types.IrType -import org.jetbrains.kotlin.ir.util.name import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.utils.SmartList diff --git a/compiler/testData/writeFlags/jvm8/defaults/compatibility/defaultImplementations.kt b/compiler/testData/writeFlags/jvm8/defaults/compatibility/defaultImplementations.kt new file mode 100644 index 00000000000..59c79abb5d5 --- /dev/null +++ b/compiler/testData/writeFlags/jvm8/defaults/compatibility/defaultImplementations.kt @@ -0,0 +1,22 @@ +// !JVM_DEFAULT_MODE: compatibility +// JVM_TARGET: 1.8 +// WITH_RUNTIME + +interface A { + @JvmDefault + fun foo(x: Int = 0): Int { + return x + } +} + +// TESTED_OBJECT_KIND: innerClass +// TESTED_OBJECTS: A, DefaultImpls +// FLAGS: ACC_FINAL, ACC_STATIC, ACC_PUBLIC + +// TESTED_OBJECT_KIND: function +// TESTED_OBJECTS: A, foo$default +// FLAGS: ACC_PUBLIC, ACC_SYNTHETIC, ACC_STATIC + +// TESTED_OBJECT_KIND: function +// TESTED_OBJECTS: A$DefaultImpls, foo$default +// FLAGS: ACC_PUBLIC, ACC_SYNTHETIC, ACC_STATIC \ No newline at end of file diff --git a/compiler/testData/writeFlags/jvm8/defaults/onlyJvmDefaultsOnInterface.kt b/compiler/testData/writeFlags/jvm8/defaults/onlyJvmDefaultsOnInterface.kt new file mode 100644 index 00000000000..52c0a3599d5 --- /dev/null +++ b/compiler/testData/writeFlags/jvm8/defaults/onlyJvmDefaultsOnInterface.kt @@ -0,0 +1,20 @@ +// !JVM_DEFAULT_MODE: enable +// JVM_TARGET: 1.8 +// WITH_RUNTIME + +interface Test { + @JvmDefault + fun foo(): String { + return "OK" + } + + @JvmDefault + fun bar(x: String = "OK"): String { + return x + } +} + + +// TESTED_OBJECT_KIND: innerClass +// TESTED_OBJECTS: Test, DefaultImpls +// ABSENT: TRUE \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/flags/WriteFlagsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/flags/WriteFlagsTestGenerated.java index 86faacbe235..505846bc039 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/flags/WriteFlagsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/flags/WriteFlagsTestGenerated.java @@ -756,6 +756,11 @@ public class WriteFlagsTestGenerated extends AbstractWriteFlagsTest { runTest("compiler/testData/writeFlags/jvm8/defaults/defaultProperty.kt"); } + @TestMetadata("onlyJvmDefaultsOnInterface.kt") + public void testOnlyJvmDefaultsOnInterface() throws Exception { + runTest("compiler/testData/writeFlags/jvm8/defaults/onlyJvmDefaultsOnInterface.kt"); + } + @TestMetadata("propertyAnnotation.kt") public void testPropertyAnnotation() throws Exception { runTest("compiler/testData/writeFlags/jvm8/defaults/propertyAnnotation.kt"); @@ -773,6 +778,11 @@ public class WriteFlagsTestGenerated extends AbstractWriteFlagsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/writeFlags/jvm8/defaults/compatibility"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("defaultImplementations.kt") + public void testDefaultImplementations() throws Exception { + runTest("compiler/testData/writeFlags/jvm8/defaults/compatibility/defaultImplementations.kt"); + } + @TestMetadata("propertyAccessors.kt") public void testPropertyAccessors() throws Exception { runTest("compiler/testData/writeFlags/jvm8/defaults/compatibility/propertyAccessors.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrWriteFlagsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrWriteFlagsTestGenerated.java index 7c78ee96a47..a4540d053f2 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrWriteFlagsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrWriteFlagsTestGenerated.java @@ -756,6 +756,11 @@ public class IrWriteFlagsTestGenerated extends AbstractIrWriteFlagsTest { runTest("compiler/testData/writeFlags/jvm8/defaults/defaultProperty.kt"); } + @TestMetadata("onlyJvmDefaultsOnInterface.kt") + public void testOnlyJvmDefaultsOnInterface() throws Exception { + runTest("compiler/testData/writeFlags/jvm8/defaults/onlyJvmDefaultsOnInterface.kt"); + } + @TestMetadata("propertyAnnotation.kt") public void testPropertyAnnotation() throws Exception { runTest("compiler/testData/writeFlags/jvm8/defaults/propertyAnnotation.kt"); @@ -773,6 +778,11 @@ public class IrWriteFlagsTestGenerated extends AbstractIrWriteFlagsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/writeFlags/jvm8/defaults/compatibility"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); } + @TestMetadata("defaultImplementations.kt") + public void testDefaultImplementations() throws Exception { + runTest("compiler/testData/writeFlags/jvm8/defaults/compatibility/defaultImplementations.kt"); + } + @TestMetadata("propertyAccessors.kt") public void testPropertyAccessors() throws Exception { runTest("compiler/testData/writeFlags/jvm8/defaults/compatibility/propertyAccessors.kt");