JVM_IR: fix inner class attributes for private class in interface

This commit is contained in:
Dmitry Petrov
2020-07-23 15:46:43 +03:00
parent 0741781462
commit e2a4ca10d6
5 changed files with 48 additions and 25 deletions
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.backend.common.lower.allOverridden
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
import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.*
@@ -33,7 +32,7 @@ import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.inline.* import org.jetbrains.kotlin.resolve.inline.INLINE_ONLY_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature
import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
@@ -73,8 +72,7 @@ val IrClass.isJvmInterface get() = isAnnotationClass || isInterface
val IrDeclaration.fileParent: IrFile val IrDeclaration.fileParent: IrFile
get() { get() {
val myParent = parent return when (val myParent = parent) {
return when (myParent) {
is IrFile -> myParent is IrFile -> myParent
else -> (myParent as IrDeclaration).fileParent else -> (myParent as IrDeclaration).fileParent
} }
@@ -103,7 +101,7 @@ fun JvmBackendContext.getSourceMapper(declaration: IrClass): SourceMapper {
} }
val IrType.isExtensionFunctionType: Boolean val IrType.isExtensionFunctionType: Boolean
get() = isFunctionTypeOrSubtype() && hasAnnotation(KotlinBuiltIns.FQ_NAMES.extensionFunctionType) get() = isFunctionTypeOrSubtype() && hasAnnotation(FQ_NAMES.extensionFunctionType)
/* Borrowed with modifications from MemberCodegen.java */ /* Borrowed with modifications from MemberCodegen.java */
@@ -121,23 +119,13 @@ fun writeInnerClass(innerClass: IrClass, typeMapper: IrTypeMapper, context: JvmB
private val NO_FLAG_LOCAL = 0 private val NO_FLAG_LOCAL = 0
private val visibilityToAccessFlag = mapOf(
Visibilities.PRIVATE to Opcodes.ACC_PRIVATE,
Visibilities.PRIVATE_TO_THIS to Opcodes.ACC_PRIVATE,
Visibilities.PROTECTED to Opcodes.ACC_PROTECTED,
JavaVisibilities.PROTECTED_STATIC_VISIBILITY to Opcodes.ACC_PROTECTED,
JavaVisibilities.PROTECTED_AND_PACKAGE to Opcodes.ACC_PROTECTED,
Visibilities.PUBLIC to Opcodes.ACC_PUBLIC,
Visibilities.INTERNAL to Opcodes.ACC_PUBLIC,
Visibilities.LOCAL to NO_FLAG_LOCAL,
JavaVisibilities.PACKAGE_VISIBILITY to AsmUtil.NO_FLAG_PACKAGE_PRIVATE
)
private fun IrDeclaration.getVisibilityAccessFlagForAnonymous(): Int = private fun IrDeclaration.getVisibilityAccessFlagForAnonymous(): Int =
if (isInlineOrContainedInInline(parent as? IrDeclaration)) Opcodes.ACC_PUBLIC else AsmUtil.NO_FLAG_PACKAGE_PRIVATE if (isInlineOrContainedInInline(parent as? IrDeclaration)) Opcodes.ACC_PUBLIC else AsmUtil.NO_FLAG_PACKAGE_PRIVATE
fun IrClass.calculateInnerClassAccessFlags(context: JvmBackendContext): Int { fun IrClass.calculateInnerClassAccessFlags(context: JvmBackendContext): Int {
val isLambda = superTypes.any { it.safeAs<IrSimpleType>()?.classifier === context.ir.symbols.lambdaClass } val isLambda = superTypes.any {
it.safeAs<IrSimpleType>()?.classifier === context.ir.symbols.lambdaClass
}
val visibility = when { val visibility = when {
isLambda -> getVisibilityAccessFlagForAnonymous() isLambda -> getVisibilityAccessFlagForAnonymous()
visibility === Visibilities.LOCAL -> Opcodes.ACC_PUBLIC visibility === Visibilities.LOCAL -> Opcodes.ACC_PUBLIC
@@ -165,18 +153,30 @@ private fun IrClass.innerAccessFlagsForModalityAndKind(): Int {
return 0 return 0
} }
fun IrDeclarationWithVisibility.getVisibilityAccessFlag(kind: OwnerKind? = null): Int = fun IrDeclarationWithVisibility.getVisibilityAccessFlag(kind: OwnerKind? = null): Int {
specialCaseVisibility(kind) specialCaseVisibility(kind)?.let {
?: visibilityToAccessFlag[visibility] return it
?: throw IllegalStateException("$visibility is not a valid visibility in backend for ${ir2string(this)}") }
return when (visibility) {
Visibilities.PRIVATE -> Opcodes.ACC_PRIVATE
Visibilities.PRIVATE_TO_THIS -> Opcodes.ACC_PRIVATE
Visibilities.PROTECTED -> Opcodes.ACC_PROTECTED
JavaVisibilities.PROTECTED_STATIC_VISIBILITY -> Opcodes.ACC_PROTECTED
JavaVisibilities.PROTECTED_AND_PACKAGE -> Opcodes.ACC_PROTECTED
Visibilities.PUBLIC -> Opcodes.ACC_PUBLIC
Visibilities.INTERNAL -> Opcodes.ACC_PUBLIC
Visibilities.LOCAL -> NO_FLAG_LOCAL
JavaVisibilities.PACKAGE_VISIBILITY -> AsmUtil.NO_FLAG_PACKAGE_PRIVATE
else -> throw IllegalStateException("$visibility is not a valid visibility in backend for ${ir2string(this)}")
}
}
private fun IrDeclarationWithVisibility.specialCaseVisibility(kind: OwnerKind?): Int? { private fun IrDeclarationWithVisibility.specialCaseVisibility(kind: OwnerKind?): Int? {
// if (JvmCodegenUtil.isNonIntrinsicPrivateCompanionObjectInInterface(memberDescriptor)) { // if (JvmCodegenUtil.isNonIntrinsicPrivateCompanionObjectInInterface(memberDescriptor)) {
// return ACC_PUBLIC // return ACC_PUBLIC
// } // }
if (this is IrClass && Visibilities.isPrivate(visibility) && if (this is IrClass && Visibilities.isPrivate(visibility) && isCompanion && hasInterfaceParent()) {
hasInterfaceParent() // TODO: non-intrinsic
) { // TODO: non-intrinsic
return Opcodes.ACC_PUBLIC return Opcodes.ACC_PUBLIC
} }
@@ -0,0 +1,3 @@
interface IFoo {
private class Nested
}
@@ -0,0 +1,10 @@
@kotlin.Metadata
final class IFoo$Nested {
public method <init>(): void
private final inner class IFoo$Nested
}
@kotlin.Metadata
public interface IFoo {
private final inner class IFoo$Nested
}
@@ -144,6 +144,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
runTest("compiler/testData/codegen/bytecodeListing/privateDefaultSetter.kt"); runTest("compiler/testData/codegen/bytecodeListing/privateDefaultSetter.kt");
} }
@TestMetadata("privateNestedClassInInterface.kt")
public void testPrivateNestedClassInInterface() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/privateNestedClassInInterface.kt");
}
@TestMetadata("samAdapterAndInlinedOne.kt") @TestMetadata("samAdapterAndInlinedOne.kt")
public void testSamAdapterAndInlinedOne() throws Exception { public void testSamAdapterAndInlinedOne() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/samAdapterAndInlinedOne.kt"); runTest("compiler/testData/codegen/bytecodeListing/samAdapterAndInlinedOne.kt");
@@ -144,6 +144,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
runTest("compiler/testData/codegen/bytecodeListing/privateDefaultSetter.kt"); runTest("compiler/testData/codegen/bytecodeListing/privateDefaultSetter.kt");
} }
@TestMetadata("privateNestedClassInInterface.kt")
public void testPrivateNestedClassInInterface() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/privateNestedClassInInterface.kt");
}
@TestMetadata("samAdapterAndInlinedOne.kt") @TestMetadata("samAdapterAndInlinedOne.kt")
public void testSamAdapterAndInlinedOne() throws Exception { public void testSamAdapterAndInlinedOne() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/samAdapterAndInlinedOne.kt"); runTest("compiler/testData/codegen/bytecodeListing/samAdapterAndInlinedOne.kt");