JVM IR: Do not generate DefaultImpls if it's empty. This revealed that InterfaceDelegationLowering was relying on the presence of DefaultImpls even when empty. Hence, simply dropping it from InterfaceLowering was not trivial. Moved default delegation in DefaultImpls to SuperType.DefaultImpls to InterfaceLowering. Clean up logic considerably, and document inter-phase dependencies.

This commit is contained in:
Kristoffer Andersen
2019-10-01 12:35:04 +02:00
committed by max-kammerer
parent cc6252098f
commit 9d1d6a7b1f
9 changed files with 228 additions and 119 deletions
@@ -144,6 +144,13 @@ private val defaultArgumentInjectorPhase = makeIrFilePhase(
prerequisite = setOf(defaultArgumentStubPhase, callableReferencePhase) 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( private val innerClassesPhase = makeIrFilePhase(
::InnerClassesLowering, ::InnerClassesLowering,
name = "InnerClasses", name = "InnerClasses",
@@ -158,6 +165,13 @@ private val returnableBlocksPhase = makeIrFilePhase(
prerequisite = setOf(arrayConstructorPhase, assertionPhase) prerequisite = setOf(arrayConstructorPhase, assertionPhase)
) )
private val syntheticAccessorPhase = makeIrFilePhase(
::SyntheticAccessorLowering,
name = "SyntheticAccessor",
description = "Introduce synthetic accessors",
prerequisite = setOf(objectClassPhase, staticDefaultFunctionPhase, interfacePhase)
)
@Suppress("Reformat") @Suppress("Reformat")
private val jvmFilePhases = private val jvmFilePhases =
typeAliasAnnotationMethodsPhase then typeAliasAnnotationMethodsPhase then
@@ -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.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext 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.codegen.isJvmInterface
import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault
import org.jetbrains.kotlin.descriptors.Modality 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.util.*
import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.util.function.UnaryOperator
internal val interfaceDelegationPhase = makeIrFilePhase( internal val interfaceDelegationPhase = makeIrFilePhase(
::InterfaceDelegationLowering, ::InterfaceDelegationLowering,
@@ -68,95 +66,80 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl
} }
private fun generateInterfaceMethods(irClass: IrClass) { 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<IrSimpleFunction>() val toRemove = mutableListOf<IrSimpleFunction>()
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 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) // (Otherwise, delegation will be present in the parent class)
if (!isDefaultImplsGeneration && if (function.overriddenSymbols.any { !it.owner.parentAsClass.isInterface && it.owner.modality != Modality.ABSTRACT }) {
function.overriddenSymbols.any {
(!it.owner.parentAsClass.isInterface || it.owner.hasJvmDefault()) &&
it.owner.modality != Modality.ABSTRACT
}
) {
continue continue
} }
val implementation = function.resolveFakeOverride() ?: continue val implementation = function.resolveFakeOverride() ?: continue
if (!implementation.hasInterfaceParent() ||
Visibilities.isPrivate(implementation.visibility) || if (!implementation.hasInterfaceParent()
implementation.isDefinitelyNotDefaultImplsMethod() || || Visibilities.isPrivate(implementation.visibility)
implementation.isMethodOfAny() || || implementation.isDefinitelyNotDefaultImplsMethod()
(!context.state.jvmDefaultMode.isCompatibility && implementation.hasJvmDefault()) || implementation.isMethodOfAny()
|| (!context.state.jvmDefaultMode.isCompatibility && implementation.hasJvmDefault())
) { ) {
continue continue
} }
val delegation = generateDelegationToDefaultImpl(irClass, implementation, function, isDefaultImplsGeneration) toRemove.add(function)
if (!isDefaultImplsGeneration) {
toRemove.add(function) val delegation = generateDelegationToDefaultImpl(irClass, implementation, function)
replacementMap[function.symbol] = delegation.symbol irClass.declarations.add(delegation)
} replacementMap[function.symbol] = delegation.symbol
} }
irClass.declarations.removeAll(toRemove) irClass.declarations.removeAll(toRemove)
} }
private fun generateDelegationToDefaultImpl( private fun generateDelegationToDefaultImpl(
irClass: IrClass, irClass: IrClass,
interfaceFun: IrSimpleFunction, interfaceImplementation: IrSimpleFunction,
inheritedFun: IrSimpleFunction, classOverride: IrSimpleFunction
isDefaultImplsGeneration: Boolean
): IrSimpleFunction { ): IrSimpleFunction {
val defaultImplFun = context.declarationFactory.getDefaultImplsFunction(interfaceFun) val inheritedProperty = classOverride.correspondingPropertySymbol?.owner
val descriptor = DescriptorsToIrRemapper.remapDeclaredSimpleFunction(classOverride.descriptor)
val irFunction = val irFunction =
if (!isDefaultImplsGeneration) { IrFunctionImpl(
val inheritedProperty = inheritedFun.correspondingPropertySymbol?.owner UNDEFINED_OFFSET,
val descriptor = DescriptorsToIrRemapper.remapDeclaredSimpleFunction(inheritedFun.descriptor) UNDEFINED_OFFSET,
IrFunctionImpl( IrDeclarationOrigin.DEFINED,
UNDEFINED_OFFSET, IrSimpleFunctionSymbolImpl(descriptor),
UNDEFINED_OFFSET, classOverride.name,
IrDeclarationOrigin.DEFINED, Visibilities.PUBLIC,
IrSimpleFunctionSymbolImpl(descriptor), classOverride.modality,
inheritedFun.name, classOverride.returnType,
Visibilities.PUBLIC, isInline = classOverride.isInline,
inheritedFun.modality, isExternal = false,
inheritedFun.returnType, isTailrec = false,
isInline = inheritedFun.isInline, isSuspend = classOverride.isSuspend
isExternal = false, ).apply {
isTailrec = false, descriptor.bind(this)
isSuspend = inheritedFun.isSuspend parent = irClass
).apply { overriddenSymbols.addAll(classOverride.overriddenSymbols)
descriptor.bind(this) copyParameterDeclarationsFrom(classOverride)
parent = irClass annotations.addAll(classOverride.annotations)
overriddenSymbols.addAll(inheritedFun.overriddenSymbols)
copyParameterDeclarationsFrom(inheritedFun)
annotations.addAll(inheritedFun.annotations)
if (inheritedProperty != null) { if (inheritedProperty != null) {
val propertyDescriptor = DescriptorsToIrRemapper.remapDeclaredProperty(inheritedProperty.descriptor) val propertyDescriptor = DescriptorsToIrRemapper.remapDeclaredProperty(inheritedProperty.descriptor)
IrPropertyImpl( IrPropertyImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, IrPropertySymbolImpl(propertyDescriptor), UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.DEFINED, IrPropertySymbolImpl(propertyDescriptor),
inheritedProperty.name, Visibilities.PUBLIC, inheritedProperty.modality, inheritedProperty.isVar, inheritedProperty.name, Visibilities.PUBLIC, inheritedProperty.modality, inheritedProperty.isVar,
inheritedProperty.isConst, inheritedProperty.isLateinit, inheritedProperty.isDelegated, isExternal = false inheritedProperty.isConst, inheritedProperty.isLateinit, inheritedProperty.isDelegated, isExternal = false
).apply { ).apply {
propertyDescriptor.bind(this) propertyDescriptor.bind(this)
parent = irClass parent = irClass
correspondingPropertySymbol = symbol 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 { context.createIrBuilder(irFunction.symbol, UNDEFINED_OFFSET, UNDEFINED_OFFSET).apply {
irFunction.body = irBlockBody { irFunction.body = irBlockBody {
+irReturn( +irReturn(
@@ -182,7 +165,7 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl
} }
override fun visitSimpleFunction(declaration: IrSimpleFunction) { override fun visitSimpleFunction(declaration: IrSimpleFunction) {
declaration.overriddenSymbols.replaceAll(UnaryOperator { symbol -> replacementMap[symbol] ?: symbol }) declaration.overriddenSymbols.replaceAll { symbol -> replacementMap[symbol] ?: symbol }
super.visitSimpleFunction(declaration) super.visitSimpleFunction(declaration)
} }
} }
@@ -234,7 +217,8 @@ private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : Ir
val callee = expression.symbol.owner val callee = expression.symbol.owner
if (callee.parent.safeAs<IrClass>()?.isInterface != true || if (callee.parent.safeAs<IrClass>()?.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) return super.visitCall(expression)
} }
@@ -7,14 +7,17 @@ package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.ir.copyBodyToStatic 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.ir.passTypeArgumentsFrom
import org.jetbrains.kotlin.backend.common.lower.InitializersLowering.Companion.clinitName 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.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities 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.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression 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.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrLocalDelegatedPropertySymbol import org.jetbrains.kotlin.ir.symbols.IrLocalDelegatedPropertySymbol
import org.jetbrains.kotlin.ir.util.copyTypeAndValueArgumentsFrom import org.jetbrains.kotlin.ir.util.*
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.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
internal val interfacePhase = makeIrFilePhase( /**
::InterfaceLowering, * This phase moves interface members with default implementations to the
name = "Interface", * associated companion DefaultImpls with bridges, as appropriate. It then
description = "Move default implementations of interface members to DefaultImpls class" * 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 { private val removedFunctions = hashMapOf<IrFunctionSymbol, IrFunctionSymbol>()
val state = context.state
val removedFunctions = hashMapOf<IrFunctionSymbol, IrFunctionSymbol>()
override fun lower(irClass: IrClass) { override fun lower(irClass: IrClass) {
if (!irClass.isInterface) return if (!irClass.isInterface) return
val defaultImplsIrClass = context.declarationFactory.getDefaultImplsClass(irClass) 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 val members = defaultImplsIrClass.declarations
for (function in irClass.declarations) { // There are 6 cases for functions on interfaces:
if (function !is IrSimpleFunction) continue 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 if (!Visibilities.isPrivate(implementation.visibility)
&& !implementation.isMethodOfAny()
val element = context.declarationFactory.getDefaultImplsFunction(function).also { && (!implementation.hasJvmDefault() || context.state.jvmDefaultMode.isCompatibility)
if (mustMoveToDefaultImpls(function)) ) {
removedFunctions[function.symbol] = it.symbol 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 * 4) _Without_ @JvmDefault, the default implementation is moved to DefaultImpls and
) { * an abstract stub is left.
function.body = IrExpressionBodyImpl(callDefaultImpls(element, function)) */
} else { !function.hasJvmDefault() -> {
createDefaultImpl(function, members)
function.body = null function.body = null
//TODO reset modality to abstract //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 { irClass.declarations.removeAll {
it is IrFunction && removedFunctions.containsKey(it.symbol) it is IrFunction && removedFunctions.containsKey(it.symbol)
} }
@@ -99,14 +135,20 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans
delegatedPropertyArray.parent = defaultImplsIrClass delegatedPropertyArray.parent = defaultImplsIrClass
delegatedPropertyArray.initializer?.patchDeclarationParents(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 = private fun createDefaultImpl(function: IrSimpleFunction, members: MutableList<IrDeclaration>): IrSimpleFunction =
Visibilities.isPrivate(function.visibility) && function.name != clinitName || context.declarationFactory.getDefaultImplsFunction(function).also {
function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || it.body = function.body?.patchDeclarationParents(it)
function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS 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 startOffset = interfaceMethod.startOffset
val endOffset = interfaceMethod.endOffset 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 { override fun visitReturn(expression: IrReturn): IrExpression {
val newFunction = removedFunctions[expression.returnTargetSymbol]?.owner val newFunction = removedFunctions[expression.returnTargetSymbol]?.owner
return super.visitReturn( return super.visitReturn(
@@ -36,14 +36,7 @@ import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
internal val syntheticAccessorPhase = makeIrFilePhase( internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
::SyntheticAccessorLowering,
name = "SyntheticAccessor",
description = "Introduce synthetic accessors",
prerequisite = setOf(objectClassPhase, staticDefaultFunctionPhase)
)
private class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
private val pendingTransformations = mutableListOf<Function0<Unit>>() private val pendingTransformations = mutableListOf<Function0<Unit>>()
private val inlineLambdaToCallSite = mutableMapOf<IrFunction, IrDeclaration?>() private val inlineLambdaToCallSite = mutableMapOf<IrFunction, IrDeclaration?>()
@@ -11,12 +11,10 @@ import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction 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.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType 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.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
@@ -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
@@ -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
@@ -756,6 +756,11 @@ public class WriteFlagsTestGenerated extends AbstractWriteFlagsTest {
runTest("compiler/testData/writeFlags/jvm8/defaults/defaultProperty.kt"); 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") @TestMetadata("propertyAnnotation.kt")
public void testPropertyAnnotation() throws Exception { public void testPropertyAnnotation() throws Exception {
runTest("compiler/testData/writeFlags/jvm8/defaults/propertyAnnotation.kt"); 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); 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") @TestMetadata("propertyAccessors.kt")
public void testPropertyAccessors() throws Exception { public void testPropertyAccessors() throws Exception {
runTest("compiler/testData/writeFlags/jvm8/defaults/compatibility/propertyAccessors.kt"); runTest("compiler/testData/writeFlags/jvm8/defaults/compatibility/propertyAccessors.kt");
@@ -756,6 +756,11 @@ public class IrWriteFlagsTestGenerated extends AbstractIrWriteFlagsTest {
runTest("compiler/testData/writeFlags/jvm8/defaults/defaultProperty.kt"); 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") @TestMetadata("propertyAnnotation.kt")
public void testPropertyAnnotation() throws Exception { public void testPropertyAnnotation() throws Exception {
runTest("compiler/testData/writeFlags/jvm8/defaults/propertyAnnotation.kt"); 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); 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") @TestMetadata("propertyAccessors.kt")
public void testPropertyAccessors() throws Exception { public void testPropertyAccessors() throws Exception {
runTest("compiler/testData/writeFlags/jvm8/defaults/compatibility/propertyAccessors.kt"); runTest("compiler/testData/writeFlags/jvm8/defaults/compatibility/propertyAccessors.kt");