[FIR2IR] Cache Java field-based properties more correctly #KT-42805 Fixed

Before this commit, we cached such IR properties by FIR property
which was created by Java field each time when we referenced it.
This led to signature clashes. Now we cache such IR properties
directly by associated FIR field.
This commit is contained in:
Mikhail Glukhikh
2020-10-19 18:21:24 +03:00
parent 3576cbf0d8
commit 23e7468e57
5 changed files with 42 additions and 21 deletions
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator
import org.jetbrains.kotlin.fir.backend.generators.DelegatedMemberGenerator
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter
import org.jetbrains.kotlin.fir.descriptors.FirBuiltInsPackageFragment
@@ -77,6 +78,10 @@ class Fir2IrDeclarationStorage(
private val initializerCache = mutableMapOf<FirAnonymousInitializer, IrAnonymousInitializer>()
private val propertyCache = mutableMapOf<FirProperty, IrProperty>()
// For pure fields (from Java) only
private val fieldToPropertyCache = mutableMapOf<FirField, IrProperty>()
private val delegatedReverseCache = mutableMapOf<IrDeclaration, FirDeclaration>()
private val fieldCache = mutableMapOf<FirField, IrField>()
@@ -669,6 +674,33 @@ class Fir2IrDeclarationStorage(
return createIrProperty(property, irParent, isLocal = isLocal)
}
fun getOrCreateIrPropertyByPureField(
field: FirField,
irParent: IrDeclarationParent
): IrProperty {
fieldToPropertyCache[field]?.let { return it }
return createIrProperty(field.toStubProperty(), irParent).apply {
fieldToPropertyCache[field] = this
}
}
private fun FirField.toStubProperty(): FirProperty {
val field = this
return buildProperty {
source = field.source
session = field.session
origin = field.origin
returnTypeRef = field.returnTypeRef
name = field.name
isVar = field.isVar
getter = field.getter
setter = field.setter
symbol = FirPropertySymbol(field.symbol.callableId)
isLocal = false
status = field.status
}
}
fun createIrProperty(
property: FirProperty,
irParent: IrDeclarationParent?,
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.psi
@@ -94,9 +93,7 @@ class CallAndReferenceGenerator(
// Since it's used as a field reference, we need a bogus property as a placeholder.
val firSymbol =
(callableReferenceAccess.calleeReference as FirResolvedNamedReference).resolvedSymbol as FirFieldSymbol
declarationStorage.getOrCreateIrProperty(
firSymbol.fir.toProperty(), referencedField.parent
).symbol
declarationStorage.getOrCreateIrPropertyByPureField(firSymbol.fir, referencedField.parent).symbol
}
IrPropertyReferenceImpl(
startOffset, endOffset, type,
@@ -147,21 +144,6 @@ class CallAndReferenceGenerator(
}.applyTypeArguments(callableReferenceAccess).applyReceivers(callableReferenceAccess, explicitReceiverExpression)
}
private fun FirField.toProperty(): FirProperty =
buildProperty {
source = this@toProperty.source
session = this@toProperty.session
origin = this@toProperty.origin
returnTypeRef = this@toProperty.returnTypeRef
name = this@toProperty.name
isVar = this@toProperty.isVar
getter = this@toProperty.getter
setter = this@toProperty.setter
symbol = FirPropertySymbol(this@toProperty.symbol.callableId)
isLocal = false
status = this@toProperty.status
}
private fun FirQualifiedAccess.tryConvertToSamConstructorCall(type: IrType): IrTypeOperatorCall? {
val calleeReference = calleeReference as? FirResolvedNamedReference ?: return null
val fir = calleeReference.resolvedSymbol.fir
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_REFLECT
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_REFLECT
// FILE: test/J.java
@@ -0,0 +1,9 @@
FILE fqName:<root> fileName:/SameJavaFieldReferences.kt
FUN name:foo visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
VAR name:ref1 type:kotlin.reflect.KProperty0<kotlin.String?> [val]
PROPERTY_REFERENCE 'public final someJavaField: kotlin.String? [val]' field='FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:someJavaField type:kotlin.String? visibility:public [final,static]' getter=null setter=null type=kotlin.reflect.KProperty0<kotlin.String?> origin=null
<1>: <none>
VAR name:ref2 type:kotlin.reflect.KProperty0<kotlin.String?> [val]
PROPERTY_REFERENCE 'public final someJavaField: kotlin.String? [val]' field='FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:someJavaField type:kotlin.String? visibility:public [final,static]' getter=null setter=null type=kotlin.reflect.KProperty0<kotlin.String?> origin=null
<1>: <none>