diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt index b02c2e80e92..8051fe085f7 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt @@ -6,13 +6,14 @@ package org.jetbrains.kotlin.backend.jvm.ir import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrTypeParameter +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.classifierOrNull +import org.jetbrains.kotlin.ir.util.hasAnnotation +import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_DEFAULT_FQ_NAME /** * Computes the erased class for this type parameter according to the java erasure rules. @@ -37,3 +38,8 @@ val IrType.erasedUpperBound: IrClass is IrTypeParameterSymbol -> classifier.owner.erasedUpperBound else -> throw IllegalStateException() } + +val IrFunction.propertyIfAccessor: IrDeclaration + get() = (this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner ?: this + +fun IrFunction.hasJvmDefault(): Boolean = propertyIfAccessor.hasAnnotation(JVM_DEFAULT_FQ_NAME) 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 15867caa183..055c9bc5db4 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,16 +9,22 @@ import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom +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.VariableRemapper 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.ir.hasJvmDefault import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.util.isInterface @@ -51,8 +57,15 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans val element = context.declarationFactory.getDefaultImplsFunction(function) members.add(element) element.body = function.body?.patchDeclarationParents(element) - function.body = null - //TODO reset modality to abstract + if (function.hasJvmDefault() && + function.origin != JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS + ) { + // TODO: don't touch function and only generate element / DefaultImpls when needed. + function.body = IrExpressionBodyImpl(callDefaultImpls(element, function)) + } else { + function.body = null + //TODO reset modality to abstract + } } } @@ -67,6 +80,26 @@ private class InterfaceLowering(val context: JvmBackendContext) : IrElementTrans Visibilities.isPrivate(function.visibility) && function.name != clinitName || function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER || function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS + + private fun callDefaultImpls(defaultImpls: IrFunction, interfaceMethod: IrFunction): IrCall { + val startOffset = interfaceMethod.startOffset + val endOffset = interfaceMethod.endOffset + + return IrCallImpl(interfaceMethod.startOffset, interfaceMethod.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)) + } + } + } } diff --git a/compiler/testData/codegen/box/jvm8/defaults/compatibility/bridge.kt b/compiler/testData/codegen/box/jvm8/defaults/compatibility/bridge.kt index ae9128d817f..4d0b1343e1b 100644 --- a/compiler/testData/codegen/box/jvm8/defaults/compatibility/bridge.kt +++ b/compiler/testData/codegen/box/jvm8/defaults/compatibility/bridge.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: compatibility -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // FILE: Simple.java diff --git a/compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedJvmDefault.kt b/compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedJvmDefault.kt index 49a5733ea0b..f031ef38328 100644 --- a/compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedJvmDefault.kt +++ b/compiler/testData/codegen/box/jvm8/defaults/compatibility/inheritedJvmDefault.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: compatibility -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // FILE: Simple.java diff --git a/compiler/testData/codegen/box/jvm8/defaults/compatibility/simpleFunction.kt b/compiler/testData/codegen/box/jvm8/defaults/compatibility/simpleFunction.kt index d64e63ffb0d..f5d9c43ba3c 100644 --- a/compiler/testData/codegen/box/jvm8/defaults/compatibility/simpleFunction.kt +++ b/compiler/testData/codegen/box/jvm8/defaults/compatibility/simpleFunction.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: compatibility -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // FILE: Simple.java diff --git a/compiler/testData/codegen/box/jvm8/defaults/inlineProperty.kt b/compiler/testData/codegen/box/jvm8/defaults/inlineProperty.kt index dae36c145db..5599ca7c425 100644 --- a/compiler/testData/codegen/box/jvm8/defaults/inlineProperty.kt +++ b/compiler/testData/codegen/box/jvm8/defaults/inlineProperty.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: enable -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // JVM_TARGET: 1.8 // WITH_RUNTIME diff --git a/compiler/testData/writeFlags/jvm8/defaults/defaultProperty.kt b/compiler/testData/writeFlags/jvm8/defaults/defaultProperty.kt index 69727a7b24a..7363d499b23 100644 --- a/compiler/testData/writeFlags/jvm8/defaults/defaultProperty.kt +++ b/compiler/testData/writeFlags/jvm8/defaults/defaultProperty.kt @@ -1,5 +1,4 @@ // !JVM_DEFAULT_MODE: enable -// IGNORE_BACKEND: JVM_IR // JVM_TARGET: 1.8 // WITH_RUNTIME