Support jvm default methods in IR

Fix several bugs around DefaultImpls
This commit is contained in:
Mikhail Bogdanov
2020-03-29 12:52:29 +02:00
parent e45a892499
commit b787c8c011
26 changed files with 373 additions and 53 deletions
@@ -14831,11 +14831,21 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/jvm8/defaults/defaultArgs.kt");
}
@TestMetadata("defaultArgsViaAnonymousObject.kt")
public void testDefaultArgsViaAnonymousObject() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/defaultArgsViaAnonymousObject.kt");
}
@TestMetadata("diamond.kt")
public void testDiamond() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/diamond.kt");
}
@TestMetadata("inheritedFunctionWithDefaultParameters.kt")
public void testInheritedFunctionWithDefaultParameters() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/inheritedFunctionWithDefaultParameters.kt");
}
@TestMetadata("inline.kt")
public void testInline() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/inline.kt");
@@ -15013,6 +15023,16 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/interfaceExtension.kt");
}
@TestMetadata("kt14243.kt")
public void testKt14243() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/kt14243.kt");
}
@TestMetadata("kt14243_2.kt")
public void testKt14243_2() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/kt14243_2.kt");
}
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/privateFunInInterface.kt");
@@ -15237,6 +15257,16 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/interfaceExtension.kt");
}
@TestMetadata("kt14243.kt")
public void testKt14243() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/kt14243.kt");
}
@TestMetadata("kt14243_2.kt")
public void testKt14243_2() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/kt14243_2.kt");
}
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/privateFunInInterface.kt");
@@ -27752,6 +27782,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/traits"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("defaultImplCall.kt")
public void testDefaultImplCall() throws Exception {
runTest("compiler/testData/codegen/box/traits/defaultImplCall.kt");
}
@TestMetadata("diamondPropertyAccessors.kt")
public void testDiamondPropertyAccessors() throws Exception {
runTest("compiler/testData/codegen/box/traits/diamondPropertyAccessors.kt");
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.ir.getJvmNameFromAnnotation
import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault
import org.jetbrains.kotlin.backend.jvm.ir.isCompiledToJvmDefault
import org.jetbrains.kotlin.backend.jvm.ir.propertyIfAccessor
import org.jetbrains.kotlin.backend.jvm.lower.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
@@ -358,7 +359,9 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
current = classCallable
continue
}
if (isSuperCall && !current.hasJvmDefault() && !current.parentAsClass.isInterface) {
if (isSuperCall && !current.parentAsClass.isInterface &&
current.resolveFakeOverride()?.isCompiledToJvmDefault(context.state.jvmDefaultMode) != true
) {
return current
}
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDeclarationFactory
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
@@ -28,6 +29,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.*
@@ -38,8 +40,10 @@ import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_DEFAULT_FQ_NAME
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
/**
* Perform as much type erasure as is significant for JVM signature generation.
@@ -143,6 +147,13 @@ fun IrDeclaration.getJvmNameFromAnnotation(): String? {
val IrFunction.propertyIfAccessor: IrDeclaration
get() = (this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner ?: this
fun IrFunction.isCompiledToJvmDefault(jvmDefaultMode: JvmDefaultMode): Boolean {
if (hasJvmDefault()) return true
val parentDescriptor = propertyIfAccessor.parentAsClass.descriptor
if (parentDescriptor !is DeserializedClassDescriptor) return jvmDefaultMode.forAllMehtodsWithBody
return JvmProtoBufUtil.isNewPlaceForBodyGeneration(parentDescriptor.classProto)
}
fun IrFunction.hasJvmDefault(): Boolean = propertyIfAccessor.hasAnnotation(JVM_DEFAULT_FQ_NAME)
fun IrFunction.hasPlatformDependent(): Boolean = propertyIfAccessor.hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME)
@@ -277,7 +288,15 @@ fun IrFunctionAccessExpression.copyFromWithPlaceholderTypeArguments(existingCall
// 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.
val IrSimpleFunction.isJvmAbstract: Boolean
get() = (modality == Modality.ABSTRACT) ||
(parentAsClass.isJvmInterface && !hasJvmDefault() && !hasPlatformDependent()
&& (!isFakeOverride || overriddenSymbols.all { it.owner.isJvmAbstract }))
fun IrSimpleFunction.isJvmAbstract(jvmDefaultMode: JvmDefaultMode): Boolean = (modality == Modality.ABSTRACT) ||
(parentAsClass.isJvmInterface && resolveFakeOverride()?.run { !isCompiledToJvmDefault(jvmDefaultMode) && !hasPlatformDependent() } ?: true)
fun firstSuperMethodFromKotlin(
override: IrSimpleFunction,
implementation: IrSimpleFunction
): IrSimpleFunctionSymbol {
return override.overriddenSymbols.first {
val owner = it.owner
owner.modality != Modality.ABSTRACT && owner.overrides(implementation)
}
}
@@ -159,7 +159,7 @@ private class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass,
return false
// We don't produce bridges for abstract functions in interfaces.
if (irFunction.isJvmAbstract)
if (irFunction.isJvmAbstract(context.state.jvmDefaultMode))
return !irFunction.parentAsClass.isJvmInterface
// Finally, the JVM backend also ignores concrete fake overrides whose implementation is directly inherited from an interface.
@@ -213,7 +213,7 @@ private class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass,
// exists in a superclass, since we do not generate bridges for fake overrides of interface methods.
if (irFunction.isFakeOverride) {
bridgeTarget = when {
irFunction.isJvmAbstract -> {
irFunction.isJvmAbstract(context.state.jvmDefaultMode) -> {
irClass.declarations.remove(irFunction)
irClass.addAbstractMethodStub(irFunction, specialBridge.methodInfo?.needsArgumentBoxing == true)
}
@@ -244,7 +244,7 @@ private class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass,
if (!irFunction.isFakeOverride && specialBridge.methodInfo != null) {
irFunction.rewriteSpecialMethodBody(targetMethod, specialBridge.signature, specialBridge.methodInfo)
}
} else if (irFunction.isJvmAbstract) {
} else if (irFunction.isJvmAbstract(context.state.jvmDefaultMode)) {
// Do not generate bridge methods for abstract methods which do not override a special bridge method.
// This matches the behavior of the JVM backend, but it does mean that we generate superfluous bridges
// for abstract methods overriding a special bridge for which we do not create a bridge due to,
@@ -270,9 +270,10 @@ private class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass,
//
// This can still break binary compatibility, but it matches the behavior of the JVM backend.
if (irFunction.isFakeOverride) {
irFunction.overriddenSymbols.asSequence().map { it.owner }.filter { !it.isJvmAbstract }.forEach { override ->
override.allOverridden().mapTo(blacklist) { it.jvmMethod }
}
irFunction.overriddenSymbols.asSequence().map { it.owner }.filter { !it.isJvmAbstract(context.state.jvmDefaultMode) }
.forEach { override ->
override.allOverridden().mapTo(blacklist) { it.jvmMethod }
}
}
generated.values.filter { it.signature !in blacklist }.forEach { irClass.addBridge(it, bridgeTarget) }
@@ -15,9 +15,8 @@ import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
import org.jetbrains.kotlin.backend.jvm.ir.createDelegatingCallWithPlaceholderTypeArguments
import org.jetbrains.kotlin.backend.jvm.ir.createPlaceholderAnyNType
import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault
import org.jetbrains.kotlin.backend.jvm.ir.*
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.deserialization.PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME
@@ -63,7 +62,7 @@ private class InheritedDefaultMethodsOnClassesLowering(val context: JvmBackendCo
private fun generateInterfaceMethods(irClass: IrClass) {
irClass.declarations.transform { declaration ->
(declaration as? IrSimpleFunction)?.findInterfaceImplementation()?.let { implementation ->
(declaration as? IrSimpleFunction)?.findInterfaceImplementation(context.state.jvmDefaultMode)?.let { implementation ->
generateDelegationToDefaultImpl(implementation, declaration)
} ?: declaration
}
@@ -74,7 +73,7 @@ private class InheritedDefaultMethodsOnClassesLowering(val context: JvmBackendCo
// if the overriden symbol has been, or will be, replaced and patch it accordingly.
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
declaration.overriddenSymbols = declaration.overriddenSymbols.map { symbol ->
if (symbol.owner.findInterfaceImplementation() != null)
if (symbol.owner.findInterfaceImplementation(context.state.jvmDefaultMode) != null)
context.declarationFactory.getDefaultImplsRedirection(symbol.owner).symbol
else symbol
}
@@ -87,15 +86,16 @@ private class InheritedDefaultMethodsOnClassesLowering(val context: JvmBackendCo
): IrSimpleFunction {
val irFunction = context.declarationFactory.getDefaultImplsRedirection(classOverride)
val defaultImplFun = context.declarationFactory.getDefaultImplsFunction(interfaceImplementation)
val superMethod = firstSuperMethodFromKotlin(irFunction, interfaceImplementation).owner
val defaultImplFun = context.declarationFactory.getDefaultImplsFunction(superMethod)
context.createIrBuilder(irFunction.symbol, UNDEFINED_OFFSET, UNDEFINED_OFFSET).apply {
irFunction.body = irBlockBody {
+irReturn(
irCall(defaultImplFun.symbol, irFunction.returnType).apply {
interfaceImplementation.parentAsClass.typeParameters.forEachIndexed { index, _ ->
superMethod.parentAsClass.typeParameters.forEachIndexed { index, _ ->
putTypeArgument(index, createPlaceholderAnyNType(context.irBuiltIns))
}
passTypeArgumentsFrom(irFunction, offset = interfaceImplementation.parentAsClass.typeParameters.size)
passTypeArgumentsFrom(irFunction, offset = superMethod.parentAsClass.typeParameters.size)
var offset = 0
irFunction.dispatchReceiverParameter?.let { putValueArgument(offset++, irGet(it)) }
@@ -128,7 +128,7 @@ private class InterfaceSuperCallsLowering(val context: JvmBackendContext) : IrEl
}
val superCallee = expression.symbol.owner as IrSimpleFunction
if (superCallee.isDefinitelyNotDefaultImplsMethod()) return super.visitCall(expression)
if (superCallee.isDefinitelyNotDefaultImplsMethod(context.state.jvmDefaultMode)) return super.visitCall(expression)
val redirectTarget = context.declarationFactory.getDefaultImplsFunction(superCallee)
val newCall = createDelegatingCallWithPlaceholderTypeArguments(expression, redirectTarget, context.irBuiltIns)
@@ -139,7 +139,7 @@ private class InterfaceSuperCallsLowering(val context: JvmBackendContext) : IrEl
internal val interfaceDefaultCallsPhase = makeIrFilePhase(
lowering = ::InterfaceDefaultCallsLowering,
name = "InterfaceDefaultCalls",
description = "Redirect interface calls with default arguments to DefaultImpls"
description = "Redirect interface calls with default arguments to DefaultImpls (except method compiled to JVM defaults)"
)
private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
@@ -153,7 +153,7 @@ private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : Ir
if (!callee.hasInterfaceParent() ||
callee.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
(callee.hasJvmDefault() && !context.state.jvmDefaultMode.isCompatibility)
callee.isCompiledToJvmDefault(context.state.jvmDefaultMode)
) {
return super.visitCall(expression)
}
@@ -171,11 +171,11 @@ private class InterfaceDefaultCallsLowering(val context: JvmBackendContext) : Ir
}
}
private fun IrSimpleFunction.isDefinitelyNotDefaultImplsMethod() =
private fun IrSimpleFunction.isDefinitelyNotDefaultImplsMethod(jvmDefaultMode: JvmDefaultMode) =
resolveFakeOverride()?.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB ||
origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ||
hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_FQ_NAME) ||
hasJvmDefault() ||
isCompiledToJvmDefault(jvmDefaultMode) ||
(name.asString() == "clone" &&
parent.safeAs<IrClass>()?.fqNameWhenAvailable?.asString() == "kotlin.Cloneable" &&
valueParameters.isEmpty())
@@ -224,7 +224,7 @@ private fun isDefaultImplsBridge(f: IrSimpleFunction) =
f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE ||
f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC
internal fun IrSimpleFunction.findInterfaceImplementation(): IrSimpleFunction? {
internal fun IrSimpleFunction.findInterfaceImplementation(jvmDefaultMode: JvmDefaultMode): IrSimpleFunction? {
if (!isFakeOverride) return null
parent.let { if (it is IrClass && it.isJvmInterface) return null }
@@ -242,7 +242,7 @@ internal fun IrSimpleFunction.findInterfaceImplementation(): IrSimpleFunction? {
if (!implementation.hasInterfaceParent()
|| Visibilities.isPrivate(implementation.visibility)
|| implementation.isDefinitelyNotDefaultImplsMethod()
|| implementation.isDefinitelyNotDefaultImplsMethod(jvmDefaultMode)
|| implementation.isMethodOfAny()
) {
return null
@@ -11,10 +11,7 @@ import org.jetbrains.kotlin.backend.common.ir.moveBodyTo
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
import org.jetbrains.kotlin.backend.jvm.ir.copyFromWithPlaceholderTypeArguments
import org.jetbrains.kotlin.backend.jvm.ir.createDelegatingCallWithPlaceholderTypeArguments
import org.jetbrains.kotlin.backend.jvm.ir.createPlaceholderAnyNType
import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault
import org.jetbrains.kotlin.backend.jvm.ir.*
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
@@ -26,6 +23,7 @@ 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
@@ -64,6 +62,7 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
}
private fun handleInterface(irClass: IrClass) {
val jvmDefaultMode = context.state.jvmDefaultMode
// There are 6 cases for functions on interfaces:
loop@ for (function in irClass.functions) {
when {
@@ -78,9 +77,9 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
* create a bridge from DefaultImpls of derived to DefaultImpls of base, unless
* - 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 mode, in which case we go via
* accessors on the parent class rather than the DefaultImpls
* - we're in -Xjvm-default=enable mode, and we have that default implementation,
* - 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
* - we're in -Xjvm-default=enable|all mode, and we have that default implementation,
* in which case we simply leave it.
*
* ```
@@ -107,13 +106,14 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
when {
Visibilities.isPrivate(implementation.visibility) || implementation.isMethodOfAny() ->
continue@loop
!implementation.hasJvmDefault() -> {
!implementation.isCompiledToJvmDefault(jvmDefaultMode) -> {
val defaultImpl = createDefaultImpl(function)
context.declarationFactory.getDefaultImplsFunction(implementation).also {
val superImpl = firstSuperMethodFromKotlin(function, implementation)
context.declarationFactory.getDefaultImplsFunction(superImpl.owner).also {
defaultImpl.bridgeToStatic(it)
}
}
context.state.jvmDefaultMode.isCompatibility -> {
jvmDefaultMode.isCompatibility -> {
val defaultImpl = createDefaultImpl(function)
defaultImpl.bridgeViaAccessorTo(function)
}
@@ -122,11 +122,11 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
}
/**
* 3) Private methods (without @JvmDefault), default parameter dispatchers (without @JvmDefault)
* 3) Private methods (not compiled to JVM defaults), default parameter dispatchers (not compiled to JVM defaults)
* and $annotation methods are always moved without bridges
*/
(Visibilities.isPrivate(function.visibility) && !function.hasJvmDefault())
|| (function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER && !function.hasJvmDefault())
(Visibilities.isPrivate(function.visibility) && !function.isCompiledToJvmDefault(jvmDefaultMode))
|| (function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER && !function.isCompiledToJvmDefault(jvmDefaultMode))
|| function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_ANNOTATIONS -> {
val defaultImpl = createDefaultImpl(function)
defaultImpl.body = function.moveBodyTo(defaultImpl)
@@ -134,10 +134,10 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
}
/**
* 4) _Without_ @JvmDefault, the default implementation is moved to DefaultImpls and
* 4) Non JVM default implementation with body is moved to DefaultImpls and
* an abstract stub is left.
*/
!function.hasJvmDefault() -> {
!function.isCompiledToJvmDefault(jvmDefaultMode) -> {
val defaultImpl = createDefaultImpl(function)
defaultImpl.body = function.moveBodyTo(defaultImpl)
function.body = null
@@ -145,9 +145,9 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
}
/**
* 5) _With_ @JvmDefault, we move and bridge if in compatibility mode, ...
* 5) JVM default declaration is bridged in DefaultImpls via accessor if in compatibility mode, ...
*/
context.state.jvmDefaultMode.isCompatibility -> {
jvmDefaultMode.isCompatibility -> {
val defaultImpl = createDefaultImpl(function)
defaultImpl.bridgeViaAccessorTo(function)
}
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
import org.jetbrains.kotlin.backend.jvm.intrinsics.receiverAndArgs
import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator
import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault
import org.jetbrains.kotlin.backend.jvm.ir.isCompiledToJvmDefault
import org.jetbrains.kotlin.backend.jvm.ir.isLambda
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.hasMangledParameters
import org.jetbrains.kotlin.codegen.syntheticAccessorToSuperSuffix
@@ -500,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) && hasJvmDefault()) "\$jd" else ""
parentAsClass.isJvmInterface -> if (!Visibilities.isPrivate(visibility) && isCompiledToJvmDefault(context.state.jvmDefaultMode)) "\$jd" else ""
// Accessor for _s_uper-qualified call
superQualifier != null -> "\$s" + superQualifier.descriptor.syntheticAccessorToSuperSuffix()
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FULL_JDK
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FILE: Simple.java
@@ -0,0 +1,24 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
interface Z<T> {
fun test(p: T): T {
return p
}
}
open class ZImpl : Z<String>
class ZImpl2 : ZImpl() {
override fun test(p: String): String {
return super.test(p)
}
}
fun box(): String {
return ZImpl2().test("OK")
}
@@ -0,0 +1,26 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
interface Z<T> {
fun test(p: T): T {
return p
}
}
open class ZImpl : Z<String>
open class ZImpl2 : Z<String>, ZImpl()
class ZImpl3 : ZImpl2() {
override fun test(p: String): String {
return super.test(p)
}
}
fun box(): String {
return ZImpl3().test("OK")
}
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FILE: Simple.java
@@ -0,0 +1,17 @@
// !JVM_DEFAULT_MODE: enable
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
interface A {
@JvmDefault
fun foo(x: String = "OK"): String {
return x
}
}
fun box(): String {
val x = object : A {}
return x.foo()
}
@@ -0,0 +1,14 @@
// !JVM_DEFAULT_MODE: enable
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
interface I {
@JvmDefault
fun foo(x: String = "OK"): String = x
}
interface J : I
object O : J
fun box(): String = O.foo()
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FILE: Simple.java
@@ -0,0 +1,24 @@
// !JVM_DEFAULT_MODE: all
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
interface Z<T> {
fun test(p: T): T {
return p
}
}
open class ZImpl : Z<String>
class ZImpl2 : ZImpl() {
override fun test(p: String): String {
return super.test(p)
}
}
fun box(): String {
return ZImpl2().test("OK")
}
@@ -0,0 +1,26 @@
// !JVM_DEFAULT_MODE: all
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
interface Z<T> {
fun test(p: T): T {
return p
}
}
open class ZImpl : Z<String>
open class ZImpl2 : Z<String>, ZImpl()
class ZImpl3 : ZImpl2() {
override fun test(p: String): String {
return super.test(p)
}
}
fun box(): String {
return ZImpl3().test("OK")
}
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FILE: Simple.java
+34
View File
@@ -0,0 +1,34 @@
// !JVM_DEFAULT_MODE: disable
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FULL_JDK
interface Test {
fun call(): List<String> = Thread.currentThread().getStackTrace().map { it.className + "." + it.methodName }
}
interface A : Test
interface B : Test
interface C: B, A
class Foo : C
class Foo2 : A, B, C
fun box(): String {
var result = Foo().call()
if (result[1] != "Test\$DefaultImpls.call") return "fail 1: ${result[1]}"
if (result[2] != "B\$DefaultImpls.call") return "fail 2: ${result[2]}"
if (result[3] != "C\$DefaultImpls.call") return "fail 3: ${result[3]}"
if (result[4] != "Foo.call") return "fail 4: ${result[4]}"
if (result[5] != "DefaultImplCallKt.box") return "fail 6: ${result[5]}"
result = Foo2().call()
if (result[1] != "Test\$DefaultImpls.call") return "fail 7: ${result[1]}"
if (result[2] != "A\$DefaultImpls.call") return "fail 8: ${result[2]}"
if (result[3] != "Foo2.call") return "fail 9: ${result[3]}"
if (result[4] != "DefaultImplCallKt.box") return "fail 10: ${result[4]}"
return "OK"
}
@@ -16046,11 +16046,21 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/jvm8/defaults/defaultArgs.kt");
}
@TestMetadata("defaultArgsViaAnonymousObject.kt")
public void testDefaultArgsViaAnonymousObject() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/defaultArgsViaAnonymousObject.kt");
}
@TestMetadata("diamond.kt")
public void testDiamond() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/diamond.kt");
}
@TestMetadata("inheritedFunctionWithDefaultParameters.kt")
public void testInheritedFunctionWithDefaultParameters() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/inheritedFunctionWithDefaultParameters.kt");
}
@TestMetadata("inline.kt")
public void testInline() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/inline.kt");
@@ -16228,6 +16238,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/interfaceExtension.kt");
}
@TestMetadata("kt14243.kt")
public void testKt14243() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/kt14243.kt");
}
@TestMetadata("kt14243_2.kt")
public void testKt14243_2() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/kt14243_2.kt");
}
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/privateFunInInterface.kt");
@@ -16452,6 +16472,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/interfaceExtension.kt");
}
@TestMetadata("kt14243.kt")
public void testKt14243() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/kt14243.kt");
}
@TestMetadata("kt14243_2.kt")
public void testKt14243_2() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/kt14243_2.kt");
}
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/privateFunInInterface.kt");
@@ -29338,6 +29368,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/traits"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("defaultImplCall.kt")
public void testDefaultImplCall() throws Exception {
runTest("compiler/testData/codegen/box/traits/defaultImplCall.kt");
}
@TestMetadata("diamondPropertyAccessors.kt")
public void testDiamondPropertyAccessors() throws Exception {
runTest("compiler/testData/codegen/box/traits/diamondPropertyAccessors.kt");
@@ -16046,11 +16046,21 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/jvm8/defaults/defaultArgs.kt");
}
@TestMetadata("defaultArgsViaAnonymousObject.kt")
public void testDefaultArgsViaAnonymousObject() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/defaultArgsViaAnonymousObject.kt");
}
@TestMetadata("diamond.kt")
public void testDiamond() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/diamond.kt");
}
@TestMetadata("inheritedFunctionWithDefaultParameters.kt")
public void testInheritedFunctionWithDefaultParameters() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/inheritedFunctionWithDefaultParameters.kt");
}
@TestMetadata("inline.kt")
public void testInline() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/inline.kt");
@@ -16228,6 +16238,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/interfaceExtension.kt");
}
@TestMetadata("kt14243.kt")
public void testKt14243() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/kt14243.kt");
}
@TestMetadata("kt14243_2.kt")
public void testKt14243_2() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/kt14243_2.kt");
}
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/privateFunInInterface.kt");
@@ -16452,6 +16472,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/interfaceExtension.kt");
}
@TestMetadata("kt14243.kt")
public void testKt14243() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/kt14243.kt");
}
@TestMetadata("kt14243_2.kt")
public void testKt14243_2() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/kt14243_2.kt");
}
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/privateFunInInterface.kt");
@@ -28155,6 +28185,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/traits"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@TestMetadata("defaultImplCall.kt")
public void testDefaultImplCall() throws Exception {
runTest("compiler/testData/codegen/box/traits/defaultImplCall.kt");
}
@TestMetadata("diamondPropertyAccessors.kt")
public void testDiamondPropertyAccessors() throws Exception {
runTest("compiler/testData/codegen/box/traits/diamondPropertyAccessors.kt");
@@ -14831,11 +14831,21 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/jvm8/defaults/defaultArgs.kt");
}
@TestMetadata("defaultArgsViaAnonymousObject.kt")
public void testDefaultArgsViaAnonymousObject() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/defaultArgsViaAnonymousObject.kt");
}
@TestMetadata("diamond.kt")
public void testDiamond() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/diamond.kt");
}
@TestMetadata("inheritedFunctionWithDefaultParameters.kt")
public void testInheritedFunctionWithDefaultParameters() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/inheritedFunctionWithDefaultParameters.kt");
}
@TestMetadata("inline.kt")
public void testInline() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/inline.kt");
@@ -15013,6 +15023,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/interfaceExtension.kt");
}
@TestMetadata("kt14243.kt")
public void testKt14243() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/kt14243.kt");
}
@TestMetadata("kt14243_2.kt")
public void testKt14243_2() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/kt14243_2.kt");
}
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/privateFunInInterface.kt");
@@ -15237,6 +15257,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/interfaceExtension.kt");
}
@TestMetadata("kt14243.kt")
public void testKt14243() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/kt14243.kt");
}
@TestMetadata("kt14243_2.kt")
public void testKt14243_2() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/kt14243_2.kt");
}
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/privateFunInInterface.kt");
@@ -27752,6 +27782,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/traits"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@TestMetadata("defaultImplCall.kt")
public void testDefaultImplCall() throws Exception {
runTest("compiler/testData/codegen/box/traits/defaultImplCall.kt");
}
@TestMetadata("diamondPropertyAccessors.kt")
public void testDiamondPropertyAccessors() throws Exception {
runTest("compiler/testData/codegen/box/traits/diamondPropertyAccessors.kt");