JVM IR: do not generate DefaultImpls delegate for collection fake overrides
In the newly added test, prior to this change, JVM IR was generating DefaultImpls classes with calls to things like `kotlin/collections/MutableList$DefaultImpls.spliterator` and other default methods present in JDK 8+. This obviously didn't make much sense. Although these weren't explicitly mentioned anywhere in the bytecode, they caused some validation tools to report errors (e.g. animalsniffer used in arrow).
This commit is contained in:
@@ -156,6 +156,7 @@ fun IrSimpleFunction.isCompiledToJvmDefault(jvmDefaultMode: JvmDefaultMode): Boo
|
||||
assert(!isFakeOverride && parentAsClass.isInterface && modality != Modality.ABSTRACT) {
|
||||
"`isCompiledToJvmDefault` should be called on non-fakeoverrides and non-abstract methods from interfaces ${ir2string(this)}"
|
||||
}
|
||||
if (origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB) return false
|
||||
if (hasJvmDefault()) return true
|
||||
val parentDescriptor = propertyIfAccessor.parentAsClass.descriptor
|
||||
if (parentDescriptor !is DeserializedClassDescriptor) return jvmDefaultMode.forAllMethodsWithBody
|
||||
|
||||
+14
-12
@@ -171,19 +171,21 @@ private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : Ir
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.isDefinitelyNotDefaultImplsMethod(jvmDefaultMode: JvmDefaultMode): Boolean {
|
||||
if (resolveFakeOverride()?.run {
|
||||
origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB || isCompiledToJvmDefault(
|
||||
jvmDefaultMode
|
||||
)
|
||||
} != false) return true
|
||||
|
||||
return origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
||||
internal fun IrSimpleFunction.isDefinitelyNotDefaultImplsMethod(
|
||||
jvmDefaultMode: JvmDefaultMode,
|
||||
implementation: IrSimpleFunction? = resolveFakeOverride()
|
||||
): Boolean =
|
||||
implementation == null ||
|
||||
implementation.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB ||
|
||||
implementation.isCompiledToJvmDefault(jvmDefaultMode) ||
|
||||
origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
||||
hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME) ||
|
||||
(name.asString() == "clone" &&
|
||||
parent.safeAs<IrClass>()?.fqNameWhenAvailable?.asString() == "kotlin.Cloneable" &&
|
||||
valueParameters.isEmpty())
|
||||
}
|
||||
isCloneableClone()
|
||||
|
||||
private fun IrSimpleFunction.isCloneableClone(): Boolean =
|
||||
name.asString() == "clone" &&
|
||||
parent.safeAs<IrClass>()?.fqNameWhenAvailable?.asString() == "kotlin.Cloneable" &&
|
||||
valueParameters.isEmpty()
|
||||
|
||||
internal val interfaceObjectCallsPhase = makeIrFilePhase(
|
||||
lowering = ::InterfaceObjectCallsLowering,
|
||||
|
||||
+2
-3
@@ -105,18 +105,17 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
|
||||
when {
|
||||
Visibilities.isPrivate(implementation.visibility) || implementation.isMethodOfAny() ->
|
||||
continue@loop
|
||||
!implementation.isCompiledToJvmDefault(jvmDefaultMode) -> {
|
||||
!function.isDefinitelyNotDefaultImplsMethod(jvmDefaultMode, implementation) -> {
|
||||
val defaultImpl = createDefaultImpl(function)
|
||||
val superImpl = firstSuperMethodFromKotlin(function, implementation)
|
||||
context.declarationFactory.getDefaultImplsFunction(superImpl.owner).also {
|
||||
defaultImpl.bridgeToStatic(it)
|
||||
}
|
||||
}
|
||||
jvmDefaultMode.isCompatibility -> {
|
||||
jvmDefaultMode.isCompatibility && implementation.isCompiledToJvmDefault(jvmDefaultMode) -> {
|
||||
val defaultImpl = createDefaultImpl(function)
|
||||
defaultImpl.bridgeViaAccessorTo(function)
|
||||
}
|
||||
// else -> Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user