JVM_IR: KT-40293 Box return type for DefaultImpls methods if required
This commit is contained in:
@@ -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 {
|
||||
|
||||
+14
-4
@@ -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 } &&
|
||||
|
||||
+4
-4
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user