JVM.IR. Add assertions for JVM defaults checks
This commit is contained in:
+5
@@ -53,6 +53,11 @@ fun CallableMemberDescriptor.isCompiledToJvmDefaultIfNoAbstract(jvmDefault: JvmD
|
||||
|
||||
val clazz = directMember.containingDeclaration
|
||||
|
||||
// TODO add checks after fixes in diagnostics
|
||||
// assert(this.kind.isReal && isInterface(clazz) && modality != Modality.ABSTRACT) {
|
||||
// "`isCompiledToJvmDefault` should be called on non-fakeoverrides and non-abstract methods from interfaces $this"
|
||||
// }
|
||||
|
||||
if (directMember.annotations.hasAnnotation(JVM_DEFAULT_FQ_NAME)) return true
|
||||
if (clazz !is DeserializedClassDescriptor) return jvmDefault.forAllMethodsWithBody
|
||||
return JvmProtoBufUtil.isNewPlaceForBodyGeneration(clazz.classProto)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||
import org.jetbrains.kotlin.backend.common.lower.IrLoweringContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
@@ -147,10 +148,17 @@ fun IrDeclaration.getJvmNameFromAnnotation(): String? {
|
||||
val IrFunction.propertyIfAccessor: IrDeclaration
|
||||
get() = (this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner ?: this
|
||||
|
||||
fun IrFunction.isCompiledToJvmDefault(jvmDefaultMode: JvmDefaultMode): Boolean {
|
||||
fun IrFunction.isSimpleFunctionCompiledToJvmDefault(jvmDefaultMode: JvmDefaultMode): Boolean {
|
||||
return (this as? IrSimpleFunction)?.isCompiledToJvmDefault(jvmDefaultMode) == true
|
||||
}
|
||||
|
||||
fun IrSimpleFunction.isCompiledToJvmDefault(jvmDefaultMode: JvmDefaultMode): Boolean {
|
||||
assert(!isFakeOverride && parentAsClass.isInterface && modality != Modality.ABSTRACT) {
|
||||
"`isCompiledToJvmDefault` should be called on non-fakeoverrides and non-abstract methods from interfaces ${ir2string(this)}"
|
||||
}
|
||||
if (hasJvmDefault()) return true
|
||||
val parentDescriptor = propertyIfAccessor.parentAsClass.descriptor
|
||||
if (parentDescriptor !is DeserializedClassDescriptor) return jvmDefaultMode.forAllMehtodsWithBody
|
||||
if (parentDescriptor !is DeserializedClassDescriptor) return jvmDefaultMode.forAllMethodsWithBody
|
||||
return JvmProtoBufUtil.isNewPlaceForBodyGeneration(parentDescriptor.classProto)
|
||||
}
|
||||
|
||||
@@ -286,10 +294,13 @@ fun IrFunctionAccessExpression.copyFromWithPlaceholderTypeArguments(existingCall
|
||||
|
||||
// Check whether a function maps to an abstract method.
|
||||
// For non-interface methods or interface methods coming from Java the modality is correct. Kotlin interface methods
|
||||
// are abstract unless they are annotated with @JvmDefault or @PlatformDependent or they override a method with
|
||||
// such an annotation.
|
||||
fun IrSimpleFunction.isJvmAbstract(jvmDefaultMode: JvmDefaultMode): Boolean = (modality == Modality.ABSTRACT) ||
|
||||
(parentAsClass.isJvmInterface && resolveFakeOverride()?.run { !isCompiledToJvmDefault(jvmDefaultMode) && !hasPlatformDependent() } ?: true)
|
||||
// are abstract unless they are annotated @PlatformDependent or compiled to JVM default (with @JvmDefault annotation or without)
|
||||
// or they override such method.
|
||||
fun IrSimpleFunction.isJvmAbstract(jvmDefaultMode: JvmDefaultMode): Boolean {
|
||||
if (modality == Modality.ABSTRACT) return true
|
||||
if (!parentAsClass.isJvmInterface) return false
|
||||
return resolveFakeOverride()?.run { !isCompiledToJvmDefault(jvmDefaultMode) && !hasPlatformDependent() } != false
|
||||
}
|
||||
|
||||
fun firstSuperMethodFromKotlin(
|
||||
override: IrSimpleFunction,
|
||||
|
||||
+10
-5
@@ -153,7 +153,7 @@ private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : Ir
|
||||
|
||||
if (!callee.hasInterfaceParent() ||
|
||||
callee.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
||||
callee.isCompiledToJvmDefault(context.state.jvmDefaultMode)
|
||||
callee.isSimpleFunctionCompiledToJvmDefault(context.state.jvmDefaultMode)
|
||||
) {
|
||||
return super.visitCall(expression)
|
||||
}
|
||||
@@ -171,14 +171,19 @@ private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : Ir
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.isDefinitelyNotDefaultImplsMethod(jvmDefaultMode: JvmDefaultMode) =
|
||||
resolveFakeOverride()?.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB ||
|
||||
origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
||||
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 ||
|
||||
hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME) ||
|
||||
isCompiledToJvmDefault(jvmDefaultMode) ||
|
||||
(name.asString() == "clone" &&
|
||||
parent.safeAs<IrClass>()?.fqNameWhenAvailable?.asString() == "kotlin.Cloneable" &&
|
||||
valueParameters.isEmpty())
|
||||
}
|
||||
|
||||
internal val interfaceObjectCallsPhase = makeIrFilePhase(
|
||||
lowering = ::InterfaceObjectCallsLowering,
|
||||
|
||||
+1
-2
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.ir.expressions.IrReturn
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrLocalDelegatedPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
@@ -78,7 +77,7 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
|
||||
* - the implementation is private, or belongs to java.lang.Object,
|
||||
* or is a stub for function with default parameters ($default)
|
||||
* - we're in -Xjvm-default=compatibility|all-compatibility mode, in which case we go via
|
||||
* accessors on the parent class rather than the DefaultImpls if inherited method compiled to JVM default
|
||||
* accessors on the parent class rather than the DefaultImpls if inherited method is compiled to JVM default
|
||||
* - we're in -Xjvm-default=enable|all mode, and we have that default implementation,
|
||||
* in which case we simply leave it.
|
||||
*
|
||||
|
||||
+2
-2
@@ -493,7 +493,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrFunction.accessorName(superQualifier: IrClassSymbol?): Name {
|
||||
private fun IrSimpleFunction.accessorName(superQualifier: IrClassSymbol?): Name {
|
||||
val jvmName = context.methodSignatureMapper.mapFunctionName(this)
|
||||
val suffix = when {
|
||||
// Accessors for top level functions never need a suffix.
|
||||
@@ -501,7 +501,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
|
||||
// The only function accessors placed on interfaces are for private functions and JvmDefault implementations.
|
||||
// The two cannot clash.
|
||||
parentAsClass.isJvmInterface -> if (!Visibilities.isPrivate(visibility) && isCompiledToJvmDefault(context.state.jvmDefaultMode)) "\$jd" else ""
|
||||
parentAsClass.isJvmInterface -> if (!Visibilities.isPrivate(visibility)) "\$jd" else ""
|
||||
|
||||
// Accessor for _s_uper-qualified call
|
||||
superQualifier != null -> "\$s" + superQualifier.descriptor.syntheticAccessorToSuperSuffix()
|
||||
|
||||
Reference in New Issue
Block a user