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
|
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 (directMember.annotations.hasAnnotation(JVM_DEFAULT_FQ_NAME)) return true
|
||||||
if (clazz !is DeserializedClassDescriptor) return jvmDefault.forAllMethodsWithBody
|
if (clazz !is DeserializedClassDescriptor) return jvmDefault.forAllMethodsWithBody
|
||||||
return JvmProtoBufUtil.isNewPlaceForBodyGeneration(clazz.classProto)
|
return JvmProtoBufUtil.isNewPlaceForBodyGeneration(clazz.classProto)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.ir
|
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.common.lower.IrLoweringContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
@@ -147,10 +148,17 @@ fun IrDeclaration.getJvmNameFromAnnotation(): String? {
|
|||||||
val IrFunction.propertyIfAccessor: IrDeclaration
|
val IrFunction.propertyIfAccessor: IrDeclaration
|
||||||
get() = (this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner ?: this
|
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
|
if (hasJvmDefault()) return true
|
||||||
val parentDescriptor = propertyIfAccessor.parentAsClass.descriptor
|
val parentDescriptor = propertyIfAccessor.parentAsClass.descriptor
|
||||||
if (parentDescriptor !is DeserializedClassDescriptor) return jvmDefaultMode.forAllMehtodsWithBody
|
if (parentDescriptor !is DeserializedClassDescriptor) return jvmDefaultMode.forAllMethodsWithBody
|
||||||
return JvmProtoBufUtil.isNewPlaceForBodyGeneration(parentDescriptor.classProto)
|
return JvmProtoBufUtil.isNewPlaceForBodyGeneration(parentDescriptor.classProto)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,10 +294,13 @@ fun IrFunctionAccessExpression.copyFromWithPlaceholderTypeArguments(existingCall
|
|||||||
|
|
||||||
// Check whether a function maps to an abstract method.
|
// 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
|
// 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
|
// are abstract unless they are annotated @PlatformDependent or compiled to JVM default (with @JvmDefault annotation or without)
|
||||||
// such an annotation.
|
// or they override such method.
|
||||||
fun IrSimpleFunction.isJvmAbstract(jvmDefaultMode: JvmDefaultMode): Boolean = (modality == Modality.ABSTRACT) ||
|
fun IrSimpleFunction.isJvmAbstract(jvmDefaultMode: JvmDefaultMode): Boolean {
|
||||||
(parentAsClass.isJvmInterface && resolveFakeOverride()?.run { !isCompiledToJvmDefault(jvmDefaultMode) && !hasPlatformDependent() } ?: true)
|
if (modality == Modality.ABSTRACT) return true
|
||||||
|
if (!parentAsClass.isJvmInterface) return false
|
||||||
|
return resolveFakeOverride()?.run { !isCompiledToJvmDefault(jvmDefaultMode) && !hasPlatformDependent() } != false
|
||||||
|
}
|
||||||
|
|
||||||
fun firstSuperMethodFromKotlin(
|
fun firstSuperMethodFromKotlin(
|
||||||
override: IrSimpleFunction,
|
override: IrSimpleFunction,
|
||||||
|
|||||||
+10
-5
@@ -153,7 +153,7 @@ private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : Ir
|
|||||||
|
|
||||||
if (!callee.hasInterfaceParent() ||
|
if (!callee.hasInterfaceParent() ||
|
||||||
callee.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
callee.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
||||||
callee.isCompiledToJvmDefault(context.state.jvmDefaultMode)
|
callee.isSimpleFunctionCompiledToJvmDefault(context.state.jvmDefaultMode)
|
||||||
) {
|
) {
|
||||||
return super.visitCall(expression)
|
return super.visitCall(expression)
|
||||||
}
|
}
|
||||||
@@ -171,14 +171,19 @@ private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : Ir
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrSimpleFunction.isDefinitelyNotDefaultImplsMethod(jvmDefaultMode: JvmDefaultMode) =
|
private fun IrSimpleFunction.isDefinitelyNotDefaultImplsMethod(jvmDefaultMode: JvmDefaultMode): Boolean {
|
||||||
resolveFakeOverride()?.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB ||
|
if (resolveFakeOverride()?.run {
|
||||||
origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
|
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) ||
|
hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME) ||
|
||||||
isCompiledToJvmDefault(jvmDefaultMode) ||
|
|
||||||
(name.asString() == "clone" &&
|
(name.asString() == "clone" &&
|
||||||
parent.safeAs<IrClass>()?.fqNameWhenAvailable?.asString() == "kotlin.Cloneable" &&
|
parent.safeAs<IrClass>()?.fqNameWhenAvailable?.asString() == "kotlin.Cloneable" &&
|
||||||
valueParameters.isEmpty())
|
valueParameters.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
internal val interfaceObjectCallsPhase = makeIrFilePhase(
|
internal val interfaceObjectCallsPhase = makeIrFilePhase(
|
||||||
lowering = ::InterfaceObjectCallsLowering,
|
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.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrLocalDelegatedPropertySymbol
|
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.types.defaultType
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
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,
|
* - the implementation is private, or belongs to java.lang.Object,
|
||||||
* or is a stub for function with default parameters ($default)
|
* 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
|
* - 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,
|
* - we're in -Xjvm-default=enable|all mode, and we have that default implementation,
|
||||||
* in which case we simply leave it.
|
* 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 jvmName = context.methodSignatureMapper.mapFunctionName(this)
|
||||||
val suffix = when {
|
val suffix = when {
|
||||||
// Accessors for top level functions never need a suffix.
|
// 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 only function accessors placed on interfaces are for private functions and JvmDefault implementations.
|
||||||
// The two cannot clash.
|
// 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
|
// Accessor for _s_uper-qualified call
|
||||||
superQualifier != null -> "\$s" + superQualifier.descriptor.syntheticAccessorToSuperSuffix()
|
superQualifier != null -> "\$s" + superQualifier.descriptor.syntheticAccessorToSuperSuffix()
|
||||||
|
|||||||
Reference in New Issue
Block a user