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 defaultImplsMethods = HashMap<IrSimpleFunction, IrSimpleFunction>()
|
||||||
private val defaultImplsClasses = HashMap<IrClass, IrClass>()
|
private val defaultImplsClasses = HashMap<IrClass, IrClass>()
|
||||||
private val defaultImplsRedirections = HashMap<IrSimpleFunction, IrSimpleFunction>()
|
private val defaultImplsRedirections = HashMap<IrSimpleFunction, IrSimpleFunction>()
|
||||||
|
private val defaultImplsOriginalMethods = HashMap<IrSimpleFunction, IrSimpleFunction>()
|
||||||
|
|
||||||
fun getFieldForEnumEntry(enumEntry: IrEnumEntry): IrField =
|
fun getFieldForEnumEntry(enumEntry: IrEnumEntry): IrField =
|
||||||
singletonFieldDeclarations.getOrPut(enumEntry) {
|
singletonFieldDeclarations.getOrPut(enumEntry) {
|
||||||
@@ -176,10 +177,15 @@ class JvmCachedDeclarations(
|
|||||||
it.annotations += irCall(this@JvmCachedDeclarations.context.ir.symbols.javaLangDeprecatedConstructor)
|
it.annotations += irCall(this@JvmCachedDeclarations.context.ir.symbols.javaLangDeprecatedConstructor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultImplsOriginalMethods[it] = interfaceFun
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getOriginalFunctionForDefaultImpl(defaultImplFun: IrSimpleFunction) =
|
||||||
|
defaultImplsOriginalMethods[defaultImplFun]
|
||||||
|
|
||||||
fun getDefaultImplsClass(interfaceClass: IrClass): IrClass =
|
fun getDefaultImplsClass(interfaceClass: IrClass): IrClass =
|
||||||
defaultImplsClasses.getOrPut(interfaceClass) {
|
defaultImplsClasses.getOrPut(interfaceClass) {
|
||||||
context.irFactory.buildClass {
|
context.irFactory.buildClass {
|
||||||
|
|||||||
+14
-4
@@ -171,10 +171,20 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
|
|||||||
private fun hasVoidReturnType(function: IrFunction): Boolean =
|
private fun hasVoidReturnType(function: IrFunction): Boolean =
|
||||||
function is IrConstructor || (function.returnType.isUnit() && !function.isGetter)
|
function is IrConstructor || (function.returnType.isUnit() && !function.isGetter)
|
||||||
|
|
||||||
// Copied from KotlinTypeMapper.forceBoxedReturnType.
|
// See also: KotlinTypeMapper.forceBoxedReturnType
|
||||||
private fun forceBoxedReturnType(function: IrFunction): Boolean = isBoxMethodForInlineClass(function) ||
|
private fun forceBoxedReturnType(function: IrFunction): Boolean =
|
||||||
function is IrSimpleFunction && function.returnType.isPrimitiveType() &&
|
isBoxMethodForInlineClass(function) || forceFoxedReturnTypeOnOverride(function) || forceBoxedReturnTypeOnDefaultImplFun(function)
|
||||||
function.allOverridden().any { !it.returnType.isPrimitiveType() }
|
|
||||||
|
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 =
|
private fun isBoxMethodForInlineClass(function: IrFunction): Boolean =
|
||||||
function.parent.let { it is IrClass && it.isInline } &&
|
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 jvmDefaultMode = context.state.jvmDefaultMode
|
||||||
val isCompatibilityMode = jvmDefaultMode.isCompatibility && !irClass.hasJvmDefaultNoCompatibilityAnnotation()
|
val isCompatibilityMode = jvmDefaultMode.isCompatibility && !irClass.hasJvmDefaultNoCompatibilityAnnotation()
|
||||||
// There are 6 cases for functions on interfaces:
|
// There are 6 cases for functions on interfaces:
|
||||||
loop@ for (function in irClass.functions) {
|
for (function in irClass.functions) {
|
||||||
when {
|
when {
|
||||||
/**
|
/**
|
||||||
* 1) They are plain abstract interface functions, in which case we leave them:
|
* 1) They are plain abstract interface functions, in which case we leave them:
|
||||||
*/
|
*/
|
||||||
function.modality == Modality.ABSTRACT ->
|
function.modality == Modality.ABSTRACT ->
|
||||||
continue@loop
|
continue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 2) They inherit a default implementation from an interface this interface extends:
|
* 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
|
// (KT-36188) where there could be multiple implementations. (resolveFakeOverride() only returns the implementation if
|
||||||
// there's only one.)
|
// there's only one.)
|
||||||
if (function.name.asString().endsWith("\$default")) {
|
if (function.name.asString().endsWith("\$default")) {
|
||||||
continue@loop
|
continue
|
||||||
}
|
}
|
||||||
val implementation = function.resolveFakeOverride() ?: error("No single implementation found for: ${function.render()}")
|
val implementation = function.resolveFakeOverride() ?: error("No single implementation found for: ${function.render()}")
|
||||||
|
|
||||||
when {
|
when {
|
||||||
Visibilities.isPrivate(implementation.visibility) || implementation.isMethodOfAny() ->
|
Visibilities.isPrivate(implementation.visibility) || implementation.isMethodOfAny() ->
|
||||||
continue@loop
|
continue
|
||||||
!function.isDefinitelyNotDefaultImplsMethod(jvmDefaultMode, implementation) -> {
|
!function.isDefinitelyNotDefaultImplsMethod(jvmDefaultMode, implementation) -> {
|
||||||
val defaultImpl = createDefaultImpl(function)
|
val defaultImpl = createDefaultImpl(function)
|
||||||
val superImpl = firstSuperMethodFromKotlin(function, implementation)
|
val superImpl = firstSuperMethodFromKotlin(function, implementation)
|
||||||
|
|||||||
-1
@@ -1,7 +1,6 @@
|
|||||||
// !JVM_DEFAULT_MODE: all-compatibility
|
// !JVM_DEFAULT_MODE: all-compatibility
|
||||||
// JVM_TARGET: 1.8
|
// JVM_TARGET: 1.8
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
|
|
||||||
interface Base {
|
interface Base {
|
||||||
fun test(): Int? = 0
|
fun test(): Int? = 0
|
||||||
|
|||||||
-1
@@ -1,7 +1,6 @@
|
|||||||
// !JVM_DEFAULT_MODE: all-compatibility
|
// !JVM_DEFAULT_MODE: all-compatibility
|
||||||
// JVM_TARGET: 1.8
|
// JVM_TARGET: 1.8
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
interface Base {
|
interface Base {
|
||||||
fun test(): Int? = 0
|
fun test(): Int? = 0
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user