JVM_IR KT-43440 private-to-this default interface funs are private
This commit is contained in:
+41
-28
@@ -150,39 +150,52 @@ class JvmCachedDeclarations(
|
||||
return defaultImplsMethods.getOrPut(interfaceFun) {
|
||||
val defaultImpls = getDefaultImplsClass(interfaceFun.parentAsClass)
|
||||
|
||||
// If `interfaceFun` is not a real implementation, then we're generating stubs in a descendant
|
||||
// interface's DefaultImpls. For example,
|
||||
//
|
||||
// interface I1 { fun f() { ... } }
|
||||
// interface I2 : I1
|
||||
//
|
||||
// is supposed to allow using `I2.DefaultImpls.f` as if it was inherited from `I1.DefaultImpls`.
|
||||
// The classes are not actually related and `I2.DefaultImpls.f` is not a fake override but a bridge.
|
||||
val defaultImplsOrigin = when {
|
||||
!forCompatibilityMode && !interfaceFun.isFakeOverride ->
|
||||
when {
|
||||
interfaceFun.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER ->
|
||||
interfaceFun.origin
|
||||
interfaceFun.origin.isSynthetic ->
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_WITH_MOVED_RECEIVERS_SYNTHETIC
|
||||
else ->
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_WITH_MOVED_RECEIVERS
|
||||
}
|
||||
interfaceFun.resolveFakeOverride()!!.origin.isSynthetic ->
|
||||
if (forCompatibilityMode)
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC
|
||||
else
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC
|
||||
else ->
|
||||
if (forCompatibilityMode)
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY
|
||||
else
|
||||
JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE
|
||||
}
|
||||
|
||||
// Interface functions are public or private, with one exception: clone in Cloneable, which is protected.
|
||||
// However, Cloneable has no DefaultImpls, so this merely replicates the incorrect behavior of the old backend.
|
||||
// We should rather not generate a bridge to clone when interface inherits from Cloneable at all.
|
||||
val defaultImplsVisibility =
|
||||
if (DescriptorVisibilities.isPrivate(interfaceFun.visibility))
|
||||
DescriptorVisibilities.PRIVATE
|
||||
else
|
||||
DescriptorVisibilities.PUBLIC
|
||||
|
||||
context.irFactory.createStaticFunctionWithReceivers(
|
||||
defaultImpls, interfaceFun.name, interfaceFun,
|
||||
dispatchReceiverType = parent.defaultType,
|
||||
// If `interfaceFun` is not a real implementation, then we're generating stubs in a descendant
|
||||
// interface's DefaultImpls. For example,
|
||||
//
|
||||
// interface I1 { fun f() { ... } }
|
||||
// interface I2 : I1
|
||||
//
|
||||
// is supposed to allow using `I2.DefaultImpls.f` as if it was inherited from `I1.DefaultImpls`.
|
||||
// The classes are not actually related and `I2.DefaultImpls.f` is not a fake override but a bridge.
|
||||
origin = when {
|
||||
!forCompatibilityMode && !interfaceFun.isFakeOverride ->
|
||||
when {
|
||||
interfaceFun.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER -> interfaceFun.origin
|
||||
interfaceFun.origin.isSynthetic -> JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_WITH_MOVED_RECEIVERS_SYNTHETIC
|
||||
else -> JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_WITH_MOVED_RECEIVERS
|
||||
}
|
||||
interfaceFun.resolveFakeOverride()!!.origin.isSynthetic ->
|
||||
if (forCompatibilityMode) JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY_SYNTHETIC
|
||||
else JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC
|
||||
else ->
|
||||
if (forCompatibilityMode) JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_FOR_COMPATIBILITY
|
||||
else JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE
|
||||
},
|
||||
origin = defaultImplsOrigin,
|
||||
// Old backend doesn't generate ACC_FINAL on DefaultImpls methods.
|
||||
modality = Modality.OPEN,
|
||||
|
||||
// Interface functions are public or private, with one exception: clone in Cloneable, which is protected.
|
||||
// However, Cloneable has no DefaultImpls, so this merely replicates the incorrect behavior of the old backend.
|
||||
// We should rather not generate a bridge to clone when interface inherits from Cloneable at all.
|
||||
visibility = if (interfaceFun.visibility == DescriptorVisibilities.PRIVATE) DescriptorVisibilities.PRIVATE else DescriptorVisibilities.PUBLIC,
|
||||
|
||||
visibility = defaultImplsVisibility,
|
||||
isFakeOverride = false,
|
||||
typeParametersFromContext = parent.typeParameters
|
||||
).also {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
interface A<in T> {
|
||||
private fun f(): T {
|
||||
TODO()
|
||||
}
|
||||
}
|
||||
|
||||
interface B<out T> {
|
||||
private fun f(): T {
|
||||
TODO()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
@kotlin.Metadata
|
||||
public final class A$DefaultImpls {
|
||||
// source: 'kt43440.kt'
|
||||
private static method f(p0: A): java.lang.Object
|
||||
public final inner class A$DefaultImpls
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public interface A {
|
||||
// source: 'kt43440.kt'
|
||||
public final inner class A$DefaultImpls
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class B$DefaultImpls {
|
||||
// source: 'kt43440.kt'
|
||||
private static method f(p0: B): java.lang.Object
|
||||
public final inner class B$DefaultImpls
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public interface B {
|
||||
// source: 'kt43440.kt'
|
||||
public final inner class B$DefaultImpls
|
||||
}
|
||||
+5
@@ -119,6 +119,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
|
||||
runTest("compiler/testData/codegen/bytecodeListing/kt43217.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt43440.kt")
|
||||
public void testKt43440() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeListing/kt43440.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localFunctionInInitBlock.kt")
|
||||
public void testLocalFunctionInInitBlock() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock.kt");
|
||||
|
||||
+5
@@ -119,6 +119,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
|
||||
runTest("compiler/testData/codegen/bytecodeListing/kt43217.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt43440.kt")
|
||||
public void testKt43440() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeListing/kt43440.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localFunctionInInitBlock.kt")
|
||||
public void testLocalFunctionInInitBlock() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeListing/localFunctionInInitBlock.kt");
|
||||
|
||||
Reference in New Issue
Block a user