JVM_IR: KT-40293 Box return type for DefaultImpls methods if required

This commit is contained in:
Dmitry Petrov
2020-07-31 10:59:21 +03:00
parent 034d5a948c
commit e11c90f26c
5 changed files with 24 additions and 10 deletions
@@ -43,6 +43,7 @@ class JvmCachedDeclarations(
private val defaultImplsMethods = HashMap<IrSimpleFunction, IrSimpleFunction>()
private val defaultImplsClasses = HashMap<IrClass, IrClass>()
private val defaultImplsRedirections = HashMap<IrSimpleFunction, IrSimpleFunction>()
private val defaultImplsOriginalMethods = HashMap<IrSimpleFunction, IrSimpleFunction>()
fun getFieldForEnumEntry(enumEntry: IrEnumEntry): IrField =
singletonFieldDeclarations.getOrPut(enumEntry) {
@@ -176,10 +177,15 @@ class JvmCachedDeclarations(
it.annotations += irCall(this@JvmCachedDeclarations.context.ir.symbols.javaLangDeprecatedConstructor)
}
}
defaultImplsOriginalMethods[it] = interfaceFun
}
}
}
fun getOriginalFunctionForDefaultImpl(defaultImplFun: IrSimpleFunction) =
defaultImplsOriginalMethods[defaultImplFun]
fun getDefaultImplsClass(interfaceClass: IrClass): IrClass =
defaultImplsClasses.getOrPut(interfaceClass) {
context.irFactory.buildClass {
@@ -171,10 +171,20 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
private fun hasVoidReturnType(function: IrFunction): Boolean =
function is IrConstructor || (function.returnType.isUnit() && !function.isGetter)
// Copied from KotlinTypeMapper.forceBoxedReturnType.
private fun forceBoxedReturnType(function: IrFunction): Boolean = isBoxMethodForInlineClass(function) ||
function is IrSimpleFunction && function.returnType.isPrimitiveType() &&
function.allOverridden().any { !it.returnType.isPrimitiveType() }
// See also: KotlinTypeMapper.forceBoxedReturnType
private fun forceBoxedReturnType(function: IrFunction): Boolean =
isBoxMethodForInlineClass(function) || forceFoxedReturnTypeOnOverride(function) || forceBoxedReturnTypeOnDefaultImplFun(function)
private fun forceFoxedReturnTypeOnOverride(function: IrFunction) =
function is IrSimpleFunction &&
function.returnType.isPrimitiveType() &&
function.allOverridden().any { !it.returnType.isPrimitiveType() }
private fun forceBoxedReturnTypeOnDefaultImplFun(function: IrFunction): Boolean {
if (function !is IrSimpleFunction) return false
val originalFun = context.cachedDeclarations.getOriginalFunctionForDefaultImpl(function) ?: return false
return forceFoxedReturnTypeOnOverride(originalFun)
}
private fun isBoxMethodForInlineClass(function: IrFunction): Boolean =
function.parent.let { it is IrClass && it.isInline } &&
@@ -64,13 +64,13 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
val jvmDefaultMode = context.state.jvmDefaultMode
val isCompatibilityMode = jvmDefaultMode.isCompatibility && !irClass.hasJvmDefaultNoCompatibilityAnnotation()
// There are 6 cases for functions on interfaces:
loop@ for (function in irClass.functions) {
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
continue
/**
* 2) They inherit a default implementation from an interface this interface extends:
@@ -99,13 +99,13 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
// (KT-36188) where there could be multiple implementations. (resolveFakeOverride() only returns the implementation if
// there's only one.)
if (function.name.asString().endsWith("\$default")) {
continue@loop
continue
}
val implementation = function.resolveFakeOverride() ?: error("No single implementation found for: ${function.render()}")
when {
Visibilities.isPrivate(implementation.visibility) || implementation.isMethodOfAny() ->
continue@loop
continue
!function.isDefinitelyNotDefaultImplsMethod(jvmDefaultMode, implementation) -> {
val defaultImpl = createDefaultImpl(function)
val superImpl = firstSuperMethodFromKotlin(function, implementation)
@@ -1,7 +1,6 @@
// !JVM_DEFAULT_MODE: all-compatibility
// JVM_TARGET: 1.8
// WITH_RUNTIME
// IGNORE_BACKEND: JVM_IR
interface Base {
fun test(): Int? = 0
@@ -1,7 +1,6 @@
// !JVM_DEFAULT_MODE: all-compatibility
// JVM_TARGET: 1.8
// WITH_RUNTIME
// IGNORE_BACKEND: JVM_IR
interface Base {
fun test(): Int? = 0
}