diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirSyntheticPropertiesStorage.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirSyntheticPropertiesStorage.kt index 535aaeabe8c..9c66a24505c 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirSyntheticPropertiesStorage.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirSyntheticPropertiesStorage.kt @@ -15,9 +15,16 @@ import org.jetbrains.kotlin.fir.java.scopes.JavaClassUseSiteMemberScope import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScopeContext.ResultOfIntersection import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol +import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.name.Name -typealias SyntheticPropertiesCache = FirCache>> +data class SyntheticPropertiesCacheKey( + val name: Name, + val receiverParameterType: ConeKotlinType?, + val contextReceiverTypes: List +) + +typealias SyntheticPropertiesCache = FirCache>> class FirSyntheticPropertiesStorage(session: FirSession) : FirSessionComponent { private val cachesFactory = session.firCachesFactory diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt index ebe6cb73ff1..80c7c626ee1 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/SignatureEnhancement.kt @@ -268,6 +268,8 @@ class FirSignatureEnhancement( val defaultQualifiers = firMethod.computeDefaultQualifiers() val overriddenMembers = precomputedOverridden ?: (firMethod as? FirSimpleFunction)?.overridden().orEmpty() + + // TODO(KT-66195) handle context receivers val hasReceiver = overriddenMembers.any { it.receiverParameter != null } val newReceiverTypeRef = if (firMethod is FirSimpleFunction && hasReceiver) { diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt index 46945b91c7d..d4bef126bf6 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty import org.jetbrains.kotlin.fir.declarations.utils.* +import org.jetbrains.kotlin.fir.java.SyntheticPropertiesCacheKey import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod import org.jetbrains.kotlin.fir.java.declarations.buildJavaMethodCopy @@ -35,6 +36,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.MembersByScope import org.jetbrains.kotlin.fir.scopes.impl.isIntersectionOverride import org.jetbrains.kotlin.fir.scopes.impl.similarFunctionsOrBothProperties import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptor +import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptorRepresentation import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef @@ -47,6 +49,7 @@ import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.types.AbstractTypeChecker +import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty import org.jetbrains.kotlin.utils.addToStdlib.runIf /** @@ -163,7 +166,12 @@ class JavaClassUseSiteMemberScope( @Suppress("UNCHECKED_CAST") for (overriddenProperty in propertiesFromSupertypes as List>) { - val overrideInClass = syntheticPropertyCache.getValue(name, this to overriddenProperty) + val key = SyntheticPropertiesCacheKey( + name, + overriddenProperty.chosenSymbol.receiverParameter?.typeRef?.coneType, + overriddenProperty.chosenSymbol.resolvedContextReceivers.ifNotEmpty { map { it.typeRef.coneType } } ?: emptyList() + ) + val overrideInClass = syntheticPropertyCache.getValue(key, this to overriddenProperty) val chosenSymbol = overrideInClass ?: overriddenProperty.chosenSymbol directOverriddenProperties[chosenSymbol] = listOf(overriddenProperty) @@ -208,18 +216,20 @@ class JavaClassUseSiteMemberScope( ): FirNamedFunctionSymbol? { val specialGetterName = if (canUseSpecialGetters) getBuiltinSpecialPropertyGetterName() else null val name = specialGetterName?.asString() ?: JvmAbi.getterName(fir.name.asString()) - return findGetterByName(name, scope) + return findGetterOverride(name, scope) } - private fun FirPropertySymbol.findGetterByName( + private fun FirPropertySymbol.findGetterOverride( getterName: String, scope: FirScope, ): FirNamedFunctionSymbol? { val propertyFromSupertype = fir val expectedReturnType = propertyFromSupertype.returnTypeRef.coneTypeSafe() + val receiverCount = (if (receiverParameter != null) 1 else 0) + resolvedContextReceivers.size return scope.getFunctions(Name.identifier(getterName)).firstNotNullOfOrNull factory@{ candidateSymbol -> val candidate = candidateSymbol.fir - if (candidate.valueParameters.isNotEmpty()) return@factory null + if (candidate.valueParameters.size != receiverCount) return@factory null + if (!checkValueParameters(candidate)) return@factory null val candidateReturnType = candidate.returnTypeRef.toConeKotlinTypeProbablyFlexible(session, typeParameterStack) @@ -239,14 +249,18 @@ class JavaClassUseSiteMemberScope( scope: FirScope, ): FirNamedFunctionSymbol? { val propertyType = fir.returnTypeRef.coneTypeSafe() ?: return null + val receiverCount = (if (receiverParameter != null) 1 else 0) + resolvedContextReceivers.size + return scope.getFunctions(Name.identifier(JvmAbi.setterName(fir.name.asString()))).firstNotNullOfOrNull factory@{ candidateSymbol -> val candidate = candidateSymbol.fir - if (candidate.valueParameters.size != 1) return@factory null + + if (candidate.valueParameters.size != receiverCount + 1) return@factory null + if (!checkValueParameters(candidate)) return@factory null if (!candidate.returnTypeRef.toConeKotlinTypeProbablyFlexible(session, typeParameterStack).isUnit) return@factory null val parameterType = - candidate.valueParameters.single().returnTypeRef.toConeKotlinTypeProbablyFlexible(session, typeParameterStack) + candidate.valueParameters.last().returnTypeRef.toConeKotlinTypeProbablyFlexible(session, typeParameterStack) candidateSymbol.takeIf { candidate.isAcceptableAsAccessorOverride() && AbstractTypeChecker.equalTypes( @@ -256,6 +270,23 @@ class JavaClassUseSiteMemberScope( } } + private fun FirPropertySymbol.checkValueParameters(candidate: FirSimpleFunction): Boolean { + var parameterIndex = 0 + for (contextReceiver in this.resolvedContextReceivers) { + if (contextReceiver.typeRef.coneType.computeJvmDescriptorRepresentation() != + candidate.valueParameters[parameterIndex++].returnTypeRef.toConeKotlinTypeProbablyFlexible(session, typeParameterStack) + .computeJvmDescriptorRepresentation() + ) { + return false + } + } + + return receiverParameter == null || + receiverParameter!!.typeRef.coneType.computeJvmDescriptorRepresentation() == + candidate.valueParameters[parameterIndex].returnTypeRef.toConeKotlinTypeProbablyFlexible(session, typeParameterStack) + .computeJvmDescriptorRepresentation() + } + private fun FirSimpleFunction.isAcceptableAsAccessorOverride(): Boolean { // We don't accept here accessors with type parameters from Kotlin to avoid strange cases like KT-59038 // However, we (temporarily, see below) accept accessors from Kotlin in general to keep K1 compatibility in cases like KT-59550 diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticProperty.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticProperty.kt index 6e37bb7fe0c..9c103533769 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticProperty.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticProperty.kt @@ -62,7 +62,7 @@ class FirSyntheticProperty @FirImplementationDetail internal constructor( get() = false override val receiverParameter: FirReceiverParameter? - get() = null + get() = getter.receiverParameter override val isVal: Boolean get() = !isVar @@ -84,7 +84,7 @@ class FirSyntheticProperty @FirImplementationDetail internal constructor( get() = FirPropertyBodyResolveState.ALL_BODIES_RESOLVED override val contextReceivers: List - get() = emptyList() + get() = getter.contextReceivers override fun acceptChildren(visitor: FirVisitor, data: D) { returnTypeRef.accept(visitor, data) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticPropertyAccessor.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticPropertyAccessor.kt index fb77f6a0361..391b1b2dcbd 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticPropertyAccessor.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/synthetic/FirSyntheticPropertyAccessor.kt @@ -47,7 +47,7 @@ class FirSyntheticPropertyAccessor @FirImplementationDetail internal constructor get() = delegate.dispatchReceiverType override val receiverParameter: FirReceiverParameter? - get() = null + get() = delegate.receiverParameter override val deprecationsProvider: DeprecationsProvider get() = delegate.deprecationsProvider @@ -75,7 +75,7 @@ class FirSyntheticPropertyAccessor @FirImplementationDetail internal constructor } override val contextReceivers: List - get() = emptyList() + get() = delegate.contextReceivers override val controlFlowGraphReference: FirControlFlowGraphReference? = null diff --git a/compiler/testData/diagnostics/tests/j+k/kjkPropertyAndExtensionProperty.fir.kt b/compiler/testData/diagnostics/tests/j+k/kjkPropertyAndExtensionProperty.fir.kt index fdd4e5ae8c3..e75a8da61fd 100644 --- a/compiler/testData/diagnostics/tests/j+k/kjkPropertyAndExtensionProperty.fir.kt +++ b/compiler/testData/diagnostics/tests/j+k/kjkPropertyAndExtensionProperty.fir.kt @@ -51,7 +51,7 @@ class F : J() { class F2 : JOverridesRegular() { fun test() { a - "".a + "".a } } @@ -65,6 +65,6 @@ class F3 : JOverridesExtension() { class F4 : JOVerridesBoth() { fun test() { a - "".a + "".a } }