diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index e3945d8b653..a0d944ba5d3 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.backend.generators import org.jetbrains.kotlin.KtFakeSourceElementKind +import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.declarations.* @@ -265,14 +266,15 @@ class CallAndReferenceGenerator( val ownContainingClass = typeRef.toIrType().classifierOrNull?.owner as? IrClass ?: return null // For static field, we shouldn't unwrap fake override in any case if (fieldSymbol.owner.isStatic) return ownContainingClass.symbol - // This means own containing class exposes original containing class, which is possible only in Java (Kotlin forbids it) - // In this case we take own containing class as qualifier symbol to avoid visibility problems (see testKt48954 as an example) - // Otherwise we should take original containing class to avoid possible clash with Kotlin backing field - if (ownContainingClass.visibility.compareTo( - originalContainingClass.visibility - ).let { it == null || it > 0 } - ) return ownContainingClass.symbol - return originalContainingClass.symbol + // Find first Java super class to avoid possible visibility exposure & separate compilation problems + var superQualifierClass = ownContainingClass + while (!superQualifierClass.isFromJava() && superQualifierClass !== originalContainingClass) { + superQualifierClass = superQualifierClass.superTypes.find { + val kind = it.getClass()?.kind + kind == ClassKind.CLASS || kind == ClassKind.ENUM_CLASS + }?.getClass() ?: break + } + return superQualifierClass.symbol } private fun FirExpression.superQualifierSymbol(): IrClassSymbol? { diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt index 1f108722637..49c7598d165 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* @@ -36,6 +37,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType +import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny import org.jetbrains.kotlin.types.KotlinType class CallGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) { @@ -198,14 +200,14 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator // For static field, we shouldn't unwrap fake override in any case if (dispatchReceiverParameter == null) return ownContainingClass val originalContainingClass = resolveFakeOverride().containingDeclaration as? ClassDescriptor ?: return ownContainingClass - // This means own containing class exposes original containing class, which is possible only in Java (Kotlin forbids it) - // In this case we take own containing class as qualifier symbol to avoid visibility problems (see testKt48954 as an example) - // Otherwise we should take original containing class to avoid possible clash with Kotlin backing field - if (ownContainingClass.visibility.compareTo( - originalContainingClass.visibility - ).let { it == null || it > 0 } - ) return ownContainingClass - return originalContainingClass + // Find first Java super class to avoid possible visibility exposure & separate compilation problems + var containingClassForField = ownContainingClass + while (context.extensions.computeExternalDeclarationOrigin(containingClassForField) != IR_EXTERNAL_JAVA_DECLARATION_STUB && + containingClassForField !== originalContainingClass + ) { + containingClassForField = containingClassForField.getSuperClassNotAny() ?: break + } + return containingClassForField } private fun generatePropertyGetterCall( diff --git a/compiler/testData/codegen/bytecodeText/javaFields.kt b/compiler/testData/codegen/bytecodeText/javaFields.kt index dbce0ae3292..cbb3edc9236 100644 --- a/compiler/testData/codegen/bytecodeText/javaFields.kt +++ b/compiler/testData/codegen/bytecodeText/javaFields.kt @@ -16,8 +16,18 @@ open class Kotlin2 : Java2() { fun test1(j: Kotlin2) = j.f +// JVM_IR_TEMPLATES +// @Kotlin2.class: +// 2 GETFIELD Java2.f : I + +// JVM_IR_TEMPLATES +// @TestKt.class: +// 2 GETFIELD Java2.f : I + +// JVM_TEMPLATES // @Kotlin2.class: // 1 GETFIELD Java2.f : I +// JVM_TEMPLATES // @TestKt.class: // 1 GETFIELD Java2.f : I \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/ambiguousFieldAccess.fir.kt.txt b/compiler/testData/ir/irText/expressions/ambiguousFieldAccess.fir.kt.txt index 15ae07ec696..2643c433634 100644 --- a/compiler/testData/ir/irText/expressions/ambiguousFieldAccess.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/ambiguousFieldAccess.fir.kt.txt @@ -13,7 +13,7 @@ class C : B { fun f(): @FlexibleNullability String? { return eval<@FlexibleNullability String?>(f = local fun (): @FlexibleNullability String? { - return (super).#x + return (super).#x } ) } diff --git a/compiler/testData/ir/irText/expressions/ambiguousFieldAccess.kt.txt b/compiler/testData/ir/irText/expressions/ambiguousFieldAccess.kt.txt index 15ae07ec696..2643c433634 100644 --- a/compiler/testData/ir/irText/expressions/ambiguousFieldAccess.kt.txt +++ b/compiler/testData/ir/irText/expressions/ambiguousFieldAccess.kt.txt @@ -13,7 +13,7 @@ class C : B { fun f(): @FlexibleNullability String? { return eval<@FlexibleNullability String?>(f = local fun (): @FlexibleNullability String? { - return (super).#x + return (super).#x } ) } diff --git a/compiler/testData/ir/irText/firProblems/typeParameterFromJavaClass.fir.kt.txt b/compiler/testData/ir/irText/firProblems/typeParameterFromJavaClass.fir.kt.txt index 837259b4f38..72870f565ad 100644 --- a/compiler/testData/ir/irText/firProblems/typeParameterFromJavaClass.fir.kt.txt +++ b/compiler/testData/ir/irText/firProblems/typeParameterFromJavaClass.fir.kt.txt @@ -1,6 +1,6 @@ fun foo(movedPaths: MutableList>) { movedPaths.forEach>(action = local fun (it: Couple) { - it(super).#second.getName() /*~> Unit */ + it(super).#second.getName() /*~> Unit */ } ) } diff --git a/compiler/testData/ir/irText/firProblems/typeParameterFromJavaClass.kt.txt b/compiler/testData/ir/irText/firProblems/typeParameterFromJavaClass.kt.txt index 2608b2357eb..05c927aa421 100644 --- a/compiler/testData/ir/irText/firProblems/typeParameterFromJavaClass.kt.txt +++ b/compiler/testData/ir/irText/firProblems/typeParameterFromJavaClass.kt.txt @@ -1,6 +1,6 @@ fun foo(movedPaths: MutableList>) { movedPaths.forEach>(action = local fun (it: Couple) { - it(super).#second /*!! FilePath */.getName() /*~> Unit */ + it(super).#second /*!! FilePath */.getName() /*~> Unit */ } ) }