Use nearest Java super qualifier for fields in IR converter
Related to KT-49507
This commit is contained in:
+10
-8
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.backend.generators
|
package org.jetbrains.kotlin.fir.backend.generators
|
||||||
|
|
||||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.backend.*
|
import org.jetbrains.kotlin.fir.backend.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
@@ -265,14 +266,15 @@ class CallAndReferenceGenerator(
|
|||||||
val ownContainingClass = typeRef.toIrType().classifierOrNull?.owner as? IrClass ?: return null
|
val ownContainingClass = typeRef.toIrType().classifierOrNull?.owner as? IrClass ?: return null
|
||||||
// For static field, we shouldn't unwrap fake override in any case
|
// For static field, we shouldn't unwrap fake override in any case
|
||||||
if (fieldSymbol.owner.isStatic) return ownContainingClass.symbol
|
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)
|
// Find first Java super class to avoid possible visibility exposure & separate compilation problems
|
||||||
// In this case we take own containing class as qualifier symbol to avoid visibility problems (see testKt48954 as an example)
|
var superQualifierClass = ownContainingClass
|
||||||
// Otherwise we should take original containing class to avoid possible clash with Kotlin backing field
|
while (!superQualifierClass.isFromJava() && superQualifierClass !== originalContainingClass) {
|
||||||
if (ownContainingClass.visibility.compareTo(
|
superQualifierClass = superQualifierClass.superTypes.find {
|
||||||
originalContainingClass.visibility
|
val kind = it.getClass()?.kind
|
||||||
).let { it == null || it > 0 }
|
kind == ClassKind.CLASS || kind == ClassKind.ENUM_CLASS
|
||||||
) return ownContainingClass.symbol
|
}?.getClass() ?: break
|
||||||
return originalContainingClass.symbol
|
}
|
||||||
|
return superQualifierClass.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirExpression.superQualifierSymbol(): IrClassSymbol? {
|
private fun FirExpression.superQualifierSymbol(): IrClassSymbol? {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.psi2ir.generators
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor
|
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.declarations.IrVariable
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
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.tasks.isDynamic
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
class CallGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
|
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
|
// For static field, we shouldn't unwrap fake override in any case
|
||||||
if (dispatchReceiverParameter == null) return ownContainingClass
|
if (dispatchReceiverParameter == null) return ownContainingClass
|
||||||
val originalContainingClass = resolveFakeOverride().containingDeclaration as? ClassDescriptor ?: 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)
|
// Find first Java super class to avoid possible visibility exposure & separate compilation problems
|
||||||
// In this case we take own containing class as qualifier symbol to avoid visibility problems (see testKt48954 as an example)
|
var containingClassForField = ownContainingClass
|
||||||
// Otherwise we should take original containing class to avoid possible clash with Kotlin backing field
|
while (context.extensions.computeExternalDeclarationOrigin(containingClassForField) != IR_EXTERNAL_JAVA_DECLARATION_STUB &&
|
||||||
if (ownContainingClass.visibility.compareTo(
|
containingClassForField !== originalContainingClass
|
||||||
originalContainingClass.visibility
|
) {
|
||||||
).let { it == null || it > 0 }
|
containingClassForField = containingClassForField.getSuperClassNotAny() ?: break
|
||||||
) return ownContainingClass
|
}
|
||||||
return originalContainingClass
|
return containingClassForField
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generatePropertyGetterCall(
|
private fun generatePropertyGetterCall(
|
||||||
|
|||||||
@@ -16,8 +16,18 @@ open class Kotlin2 : Java2() {
|
|||||||
|
|
||||||
fun test1(j: Kotlin2) = j.f
|
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:
|
// @Kotlin2.class:
|
||||||
// 1 GETFIELD Java2.f : I
|
// 1 GETFIELD Java2.f : I
|
||||||
|
|
||||||
|
// JVM_TEMPLATES
|
||||||
// @TestKt.class:
|
// @TestKt.class:
|
||||||
// 1 GETFIELD Java2.f : I
|
// 1 GETFIELD Java2.f : I
|
||||||
@@ -13,7 +13,7 @@ class C : B {
|
|||||||
|
|
||||||
fun f(): @FlexibleNullability String? {
|
fun f(): @FlexibleNullability String? {
|
||||||
return eval<@FlexibleNullability String?>(f = local fun <anonymous>(): @FlexibleNullability String? {
|
return eval<@FlexibleNullability String?>(f = local fun <anonymous>(): @FlexibleNullability String? {
|
||||||
return <this>(super<A>).#x
|
return <this>(super<B>).#x
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class C : B {
|
|||||||
|
|
||||||
fun f(): @FlexibleNullability String? {
|
fun f(): @FlexibleNullability String? {
|
||||||
return eval<@FlexibleNullability String?>(f = local fun <anonymous>(): @FlexibleNullability String? {
|
return eval<@FlexibleNullability String?>(f = local fun <anonymous>(): @FlexibleNullability String? {
|
||||||
return <this>(super<A>).#x
|
return <this>(super<B>).#x
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
fun foo(movedPaths: MutableList<Couple<FilePath>>) {
|
fun foo(movedPaths: MutableList<Couple<FilePath>>) {
|
||||||
movedPaths.forEach<Couple<FilePath>>(action = local fun <anonymous>(it: Couple<FilePath>) {
|
movedPaths.forEach<Couple<FilePath>>(action = local fun <anonymous>(it: Couple<FilePath>) {
|
||||||
it(super<Pair>).#second.getName() /*~> Unit */
|
it(super<Couple>).#second.getName() /*~> Unit */
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
fun foo(movedPaths: MutableList<Couple<FilePath>>) {
|
fun foo(movedPaths: MutableList<Couple<FilePath>>) {
|
||||||
movedPaths.forEach<Couple<FilePath>>(action = local fun <anonymous>(it: Couple<FilePath>) {
|
movedPaths.forEach<Couple<FilePath>>(action = local fun <anonymous>(it: Couple<FilePath>) {
|
||||||
it(super<Pair>).#second /*!! FilePath */.getName() /*~> Unit */
|
it(super<Couple>).#second /*!! FilePath */.getName() /*~> Unit */
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user