JVM_IR: support @JvmDefaults in compatibility mode.

This commit is contained in:
Ting-Yuan Huang
2019-05-29 11:04:10 -07:00
committed by max-kammerer
parent 1c32941949
commit a447c748bc
7 changed files with 43 additions and 9 deletions
@@ -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)
@@ -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))
}
}
}
}
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: compatibility
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM
// FILE: Simple.java
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: compatibility
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM
// FILE: Simple.java
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: compatibility
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM
// FILE: Simple.java
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: enable
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: enable
// IGNORE_BACKEND: JVM_IR
// JVM_TARGET: 1.8
// WITH_RUNTIME