K2: add dispatchReceiverForStatics to ScopeTowerLevel to avoid receiver hacks

Related to KT-55116
This commit is contained in:
Mikhail Glukhikh
2023-01-20 18:07:50 +01:00
committed by Space Team
parent d436d56871
commit 8aed6d3c4c
8 changed files with 84 additions and 64 deletions
@@ -27,6 +27,10 @@ import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
class Candidate( class Candidate(
override val symbol: FirBasedSymbol<*>, override val symbol: FirBasedSymbol<*>,
// Here we may have an ExpressionReceiverValue
// - in case a use-site receiver is explicit
// - in some cases with static entities, no matter is a use-site receiver explicit or not
// OR we may have here a kind of ImplicitReceiverValue (non-statics only)
override var dispatchReceiverValue: ReceiverValue?, override var dispatchReceiverValue: ReceiverValue?,
// In most cases, it contains zero or single element // In most cases, it contains zero or single element
// More than one, only in case of context receiver group // More than one, only in case of context receiver group
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
@@ -42,7 +41,9 @@ fun createQualifierReceiver(
} }
} }
abstract class QualifierReceiver(final override val explicitReceiver: FirExpression) : AbstractExplicitReceiver<FirResolvedQualifier>() { abstract class QualifierReceiver(
final override val explicitReceiver: FirResolvedQualifier
) : AbstractExplicitReceiver<FirResolvedQualifier>() {
abstract fun classifierScope(): FirScope? abstract fun classifierScope(): FirScope?
abstract fun callableScope(): FirScope? abstract fun callableScope(): FirScope?
} }
@@ -382,7 +382,7 @@ private class InvokeFunctionResolveTask(
) )
enumerateTowerLevels( enumerateTowerLevels(
onScope = { scope, group -> onScope = { scope, _, group ->
processLevelForRegularInvoke( processLevelForRegularInvoke(
scope.toScopeTowerLevel(extensionReceiver = invokeReceiverValue), scope.toScopeTowerLevel(extensionReceiver = invokeReceiverValue),
info, group, info, group,
@@ -5,17 +5,22 @@
package org.jetbrains.kotlin.fir.resolve.calls.tower package org.jetbrains.kotlin.fir.resolve.calls.tower
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.declarations.ContextReceiverGroup import org.jetbrains.kotlin.fir.declarations.ContextReceiverGroup
import org.jetbrains.kotlin.fir.declarations.FirTowerDataContext import org.jetbrains.kotlin.fir.declarations.FirTowerDataContext
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionStub import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionStub
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier
import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirWhenSubjectImportingScope import org.jetbrains.kotlin.fir.scopes.impl.FirWhenSubjectImportingScope
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
import org.jetbrains.kotlin.fir.util.asReversedFrozen import org.jetbrains.kotlin.fir.util.asReversedFrozen
@@ -52,9 +57,6 @@ internal class TowerDataElementsForName(
towerDataElement.contextReceiverGroup?.let { receiver -> IndexedValue(index, receiver) } towerDataElement.contextReceiverGroup?.let { receiver -> IndexedValue(index, receiver) }
} }
} }
val emptyScopes = mutableSetOf<FirScope>()
val implicitReceiverValuesWithEmptyScopes = mutableSetOf<ImplicitReceiverValue<*>>()
} }
internal abstract class FirBaseTowerResolveTask( internal abstract class FirBaseTowerResolveTask(
@@ -88,10 +90,32 @@ internal abstract class FirBaseTowerResolveTask(
withHideMembersOnly: Boolean = false, withHideMembersOnly: Boolean = false,
includeInnerConstructors: Boolean = extensionReceiver != null, includeInnerConstructors: Boolean = extensionReceiver != null,
contextReceiverGroup: ContextReceiverGroup? = null, contextReceiverGroup: ContextReceiverGroup? = null,
dispatchReceiverForStatics: ExpressionReceiverValue? = null
): ScopeTowerLevel = ScopeTowerLevel( ): ScopeTowerLevel = ScopeTowerLevel(
components, this, components, this,
givenExtensionReceiverOptions = contextReceiverGroup ?: listOfNotNull(extensionReceiver), givenExtensionReceiverOptions = contextReceiverGroup ?: listOfNotNull(extensionReceiver),
withHideMembersOnly, includeInnerConstructors withHideMembersOnly, includeInnerConstructors, dispatchReceiverForStatics
)
protected fun FirScope.toScopeTowerLevelForStaticWithImplicitDispatchReceiver(
staticOwnerOwnerSymbol: FirRegularClassSymbol? = null,
source: KtSourceElement? = null
): ScopeTowerLevel = toScopeTowerLevel(
extensionReceiver = null,
withHideMembersOnly = false,
includeInnerConstructors = false,
contextReceiverGroup = null,
staticOwnerOwnerSymbol?.let {
val resolvedQualifier = buildResolvedQualifier {
packageFqName = it.classId.packageFqName
relativeClassFqName = it.classId.relativeClassName
this.symbol = it
this.source = source?.fakeElement(KtFakeSourceElementKind.ImplicitReceiver)
}.apply {
resultType = components.typeForQualifier(this)
}
ExpressionReceiverValue(resolvedQualifier)
}
) )
protected fun ReceiverValue.toMemberScopeTowerLevel( protected fun ReceiverValue.toMemberScopeTowerLevel(
@@ -112,12 +136,12 @@ internal abstract class FirBaseTowerResolveTask(
protected inline fun enumerateTowerLevels( protected inline fun enumerateTowerLevels(
parentGroup: TowerGroup = TowerGroup.EmptyRoot, parentGroup: TowerGroup = TowerGroup.EmptyRoot,
onScope: (FirScope, TowerGroup) -> Unit, onScope: (FirScope, FirRegularClassSymbol?, TowerGroup) -> Unit,
onImplicitReceiver: (ImplicitReceiverValue<*>, TowerGroup) -> Unit, onImplicitReceiver: (ImplicitReceiverValue<*>, TowerGroup) -> Unit,
onContextReceiverGroup: (ContextReceiverGroup, TowerGroup) -> Unit, onContextReceiverGroup: (ContextReceiverGroup, TowerGroup) -> Unit,
) { ) {
for ((index, localScope) in towerDataElementsForName.reversedFilteredLocalScopes) { for ((index, localScope) in towerDataElementsForName.reversedFilteredLocalScopes) {
onScope(localScope, parentGroup.Local(index)) onScope(localScope, null, parentGroup.Local(index))
} }
for ((depth, lexical) in towerDataElementsForName.nonLocalTowerDataElements.withIndex()) { for ((depth, lexical) in towerDataElementsForName.nonLocalTowerDataElements.withIndex()) {
@@ -125,6 +149,7 @@ internal abstract class FirBaseTowerResolveTask(
if (!lexical.isLocal && scope != null) { if (!lexical.isLocal && scope != null) {
onScope( onScope(
scope, scope,
lexical.staticScopeOwnerSymbol,
if (scope is FirWhenSubjectImportingScope) TowerGroup.UnqualifiedEnum(depth) if (scope is FirWhenSubjectImportingScope) TowerGroup.UnqualifiedEnum(depth)
else parentGroup.NonLocal(depth) else parentGroup.NonLocal(depth)
) )
@@ -220,7 +245,13 @@ internal open class FirTowerResolveTask(
if (qualifierReceiver == null) return if (qualifierReceiver == null) return
val callableScope = qualifierReceiver.callableScope() ?: return val callableScope = qualifierReceiver.callableScope() ?: return
processLevel( processLevel(
callableScope.toScopeTowerLevel(includeInnerConstructors = false), callableScope.toScopeTowerLevel(
includeInnerConstructors = false,
dispatchReceiverForStatics = when (qualifierReceiver) {
is ClassQualifierReceiver -> ExpressionReceiverValue(qualifierReceiver.explicitReceiver)
else -> null
}
),
info, TowerGroup.Qualifier info, TowerGroup.Qualifier
) )
} }
@@ -256,7 +287,7 @@ internal open class FirTowerResolveTask(
enumerateTowerLevels( enumerateTowerLevels(
parentGroup = parentGroup, parentGroup = parentGroup,
onScope = { scope, group -> onScope = { scope, _, group ->
processScopeForExplicitReceiver( processScopeForExplicitReceiver(
scope, scope,
explicitReceiverValue, explicitReceiverValue,
@@ -289,13 +320,16 @@ internal open class FirTowerResolveTask(
val implicitReceiverValuesWithEmptyScopes = mutableSetOf<ImplicitReceiverValue<*>>() val implicitReceiverValuesWithEmptyScopes = mutableSetOf<ImplicitReceiverValue<*>>()
enumerateTowerLevels( enumerateTowerLevels(
onScope = l@{ scope, group -> onScope = l@{ scope, staticScopeOwnerSymbol, group ->
// NB: this check does not work for variables // NB: this check does not work for variables
// because we do not search for objects if we have extension receiver // because we do not search for objects if we have extension receiver
if (info.callKind != CallKind.VariableAccess && scope in emptyScopes) return@l if (info.callKind != CallKind.VariableAccess && scope in emptyScopes) return@l
processLevel( processLevel(
scope.toScopeTowerLevel(), info, group, scope.toScopeTowerLevelForStaticWithImplicitDispatchReceiver(
staticScopeOwnerSymbol, source = info.callSite.source
),
info, group,
onEmptyLevel = { onEmptyLevel = {
emptyScopes += scope emptyScopes += scope
} }
@@ -386,7 +420,7 @@ internal open class FirTowerResolveTask(
enumerateTowerLevels( enumerateTowerLevels(
parentGroup, parentGroup,
onScope = l@{ scope, group -> onScope = l@{ scope, _, group ->
if (scope in emptyScopes) return@l if (scope in emptyScopes) return@l
processLevel( processLevel(
@@ -425,7 +459,7 @@ internal open class FirTowerResolveTask(
enumerateTowerLevels( enumerateTowerLevels(
parentGroup, parentGroup,
onScope = { scope, towerGroup -> onScope = { scope, _, towerGroup ->
processLevel( processLevel(
scope.toScopeTowerLevel(contextReceiverGroup = contextReceiverGroup), scope.toScopeTowerLevel(contextReceiverGroup = contextReceiverGroup),
info, towerGroup, info, towerGroup,
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.fir.resolve.calls.tower
import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fakeElement import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.ContextReceiverGroup import org.jetbrains.kotlin.fir.declarations.ContextReceiverGroup
@@ -15,7 +14,6 @@ import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isInner import org.jetbrains.kotlin.fir.declarations.utils.isInner
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier
import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.*
@@ -326,7 +324,8 @@ class ScopeTowerLevel(
val scope: FirScope, val scope: FirScope,
private val givenExtensionReceiverOptions: List<ReceiverValue>, private val givenExtensionReceiverOptions: List<ReceiverValue>,
private val withHideMembersOnly: Boolean, private val withHideMembersOnly: Boolean,
private val includeInnerConstructors: Boolean private val includeInnerConstructors: Boolean,
private val dispatchReceiverForStatics: ExpressionReceiverValue?
) : TowerScopeLevel() { ) : TowerScopeLevel() {
private val session: FirSession get() = bodyResolveComponents.session private val session: FirSession get() = bodyResolveComponents.session
@@ -344,22 +343,7 @@ class ScopeTowerLevel(
return ExpressionReceiverValue(resolvedQualifier) return ExpressionReceiverValue(resolvedQualifier)
} }
private fun FirRegularClassSymbol.findJavaSuperClassSymbol(): FirRegularClassSymbol? { // For static entries we may return here FirResolvedQualifier, wrapped in ExpressionReceiverValue
var currentSymbol = this
while (currentSymbol.origin !is FirDeclarationOrigin.Java) {
var baseClassSymbol: FirRegularClassSymbol? = null
for (superType in currentSymbol.resolvedSuperTypes) {
val symbol = superType.fullyExpandedType(session).toSymbol(session)
if (symbol is FirRegularClassSymbol && symbol.classKind == ClassKind.CLASS) {
baseClassSymbol = symbol
break
}
}
currentSymbol = baseClassSymbol ?: return null
}
return currentSymbol
}
private fun dispatchReceiverValue(candidate: FirCallableSymbol<*>, callInfo: CallInfo): ReceiverValue? { private fun dispatchReceiverValue(candidate: FirCallableSymbol<*>, callInfo: CallInfo): ReceiverValue? {
candidate.fir.importedFromObjectOrStaticData?.let { data -> candidate.fir.importedFromObjectOrStaticData?.let { data ->
val objectClassId = data.objectClassId val objectClassId = data.objectClassId
@@ -369,36 +353,25 @@ class ScopeTowerLevel(
} }
} }
if (candidate is FirBackingFieldSymbol) { when {
val lookupTag = candidate.fir.propertySymbol.dispatchReceiverClassLookupTagOrNull() candidate is FirBackingFieldSymbol -> {
return when { val lookupTag = candidate.fir.propertySymbol.dispatchReceiverClassLookupTagOrNull()
lookupTag != null -> { return when {
bodyResolveComponents.implicitReceiverStack.lastDispatchReceiver { implicitReceiverValue -> lookupTag != null -> {
(implicitReceiverValue.type as? ConeClassLikeType)?.fullyExpandedType(session)?.lookupTag == lookupTag bodyResolveComponents.implicitReceiverStack.lastDispatchReceiver { implicitReceiverValue ->
(implicitReceiverValue.type as? ConeClassLikeType)?.fullyExpandedType(session)?.lookupTag == lookupTag
}
}
else -> {
bodyResolveComponents.implicitReceiverStack.lastDispatchReceiver()
} }
} }
else -> {
bodyResolveComponents.implicitReceiverStack.lastDispatchReceiver()
}
} }
} candidate.isStatic -> {
if (candidate.isStatic && candidate.isJavaOrEnhancement) { return dispatchReceiverForStatics
val explicitReceiver = callInfo.explicitReceiver
if (explicitReceiver is FirResolvedQualifier) {
return ExpressionReceiverValue(explicitReceiver)
} }
val lookupTag = candidate.fir.containingClassLookupTag() ?: return null else -> return null
val implicitDispatchReceiverValue = bodyResolveComponents.implicitReceiverStack.lastDispatchReceiver { implicitReceiverValue ->
implicitReceiverValue is ImplicitDispatchReceiverValue && implicitReceiverValue.boundSymbol.fir.isSubclassOf(
lookupTag, session, isStrict = false, lookupInterfaces = false
)
} ?: return null
// Note: we know that candidate is from Java, so normally we should find this class and its Java superclass
val regularClassSymbol = implicitDispatchReceiverValue.boundSymbol as? FirRegularClassSymbol ?: return null
return regularClassSymbol.findJavaSuperClassSymbol()?.toResolvedQualifierExpressionReceiver(callInfo.callSite.source)
} }
return null
} }
private fun shouldSkipCandidateWithInconsistentExtensionReceiver(candidate: FirCallableSymbol<*>): Boolean { private fun shouldSkipCandidateWithInconsistentExtensionReceiver(candidate: FirCallableSymbol<*>): Boolean {
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.scopes.impl.wrapNestedClassifierScopeWithSubstitutionForSuperType import org.jetbrains.kotlin.fir.scopes.impl.wrapNestedClassifierScopeWithSubstitutionForSuperType
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -78,7 +79,7 @@ fun SessionHolder.collectTowerDataElementsForClass(owner: FirClass, defaultType:
superClass.staticScope(this) superClass.staticScope(this)
?.wrapNestedClassifierScopeWithSubstitutionForSuperType(expandedType, session) ?.wrapNestedClassifierScopeWithSubstitutionForSuperType(expandedType, session)
?.asTowerDataElement(isLocal = false) ?.asTowerDataElementForStaticScope(staticScopeOwnerSymbol = superClass.symbol)
?.let(superClassesStaticsAndCompanionReceivers::add) ?.let(superClassesStaticsAndCompanionReceivers::add)
(superClass as? FirRegularClass)?.companionObjectSymbol?.let { (superClass as? FirRegularClass)?.companionObjectSymbol?.let {
@@ -223,6 +224,7 @@ class FirTowerDataElement(
val implicitReceiver: ImplicitReceiverValue<*>?, val implicitReceiver: ImplicitReceiverValue<*>?,
val contextReceiverGroup: ContextReceiverGroup? = null, val contextReceiverGroup: ContextReceiverGroup? = null,
val isLocal: Boolean, val isLocal: Boolean,
val staticScopeOwnerSymbol: FirRegularClassSymbol? = null
) { ) {
fun createSnapshot(): FirTowerDataElement = fun createSnapshot(): FirTowerDataElement =
FirTowerDataElement( FirTowerDataElement(
@@ -230,6 +232,7 @@ class FirTowerDataElement(
implicitReceiver?.createSnapshot(), implicitReceiver?.createSnapshot(),
contextReceiverGroup?.map { it.createSnapshot() }, contextReceiverGroup?.map { it.createSnapshot() },
isLocal, isLocal,
staticScopeOwnerSymbol
) )
} }
@@ -242,6 +245,9 @@ fun ContextReceiverGroup.asTowerDataElement(): FirTowerDataElement =
fun FirScope.asTowerDataElement(isLocal: Boolean): FirTowerDataElement = fun FirScope.asTowerDataElement(isLocal: Boolean): FirTowerDataElement =
FirTowerDataElement(scope = this, implicitReceiver = null, isLocal = isLocal) FirTowerDataElement(scope = this, implicitReceiver = null, isLocal = isLocal)
fun FirScope.asTowerDataElementForStaticScope(staticScopeOwnerSymbol: FirRegularClassSymbol?): FirTowerDataElement =
FirTowerDataElement(scope = this, implicitReceiver = null, isLocal = false, staticScopeOwnerSymbol = staticScopeOwnerSymbol)
fun FirClass.staticScope(sessionHolder: SessionHolder): FirContainingNamesAwareScope? = fun FirClass.staticScope(sessionHolder: SessionHolder): FirContainingNamesAwareScope? =
staticScope(sessionHolder.session, sessionHolder.scopeSession) staticScope(sessionHolder.session, sessionHolder.scopeSession)
@@ -150,7 +150,9 @@ fun FirRegularClassBuilder.generateEntriesGetter(
moduleData, FirDeclarationOrigin.Source, returnTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.EnumGeneratedDeclaration), moduleData, FirDeclarationOrigin.Source, returnTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.EnumGeneratedDeclaration),
Visibilities.Public, symbol Visibilities.Public, symbol
).apply { ).apply {
(status as FirDeclarationStatusImpl).isStatic = true this.status = createStatus(this@generateEntriesGetter.status).apply {
isStatic = true
}
} }
}.apply { }.apply {
containingClassForStaticMemberAttr = this@generateEntriesGetter.symbol.toLookupTag() containingClassForStaticMemberAttr = this@generateEntriesGetter.symbol.toLookupTag()
@@ -14,7 +14,7 @@ FILE: Child.kt
} }
public final fun foo(): R|kotlin/Unit| { public final fun foo(): R|kotlin/Unit| {
lval x: R|kotlin/String| = R|javapackage/PackagePrivateGrandparentInterface.publicStaticField| lval x: R|kotlin/String| = Q|javapackage/PublicParentClass|.R|javapackage/PackagePrivateGrandparentInterface.publicStaticField|
lval y: R|kotlin/String| = Q|javapackage/PublicParentClass|.R|javapackage/PackagePrivateGrandparentInterface.publicStaticField| lval y: R|kotlin/String| = Q|javapackage/PublicParentClass|.R|javapackage/PackagePrivateGrandparentInterface.publicStaticField|
lval z: <ERROR TYPE REF: Unresolved name: publicStaticField> = Q|javapackage/KotlinParentClass|.<Unresolved name: publicStaticField># lval z: <ERROR TYPE REF: Unresolved name: publicStaticField> = Q|javapackage/KotlinParentClass|.<Unresolved name: publicStaticField>#
} }