K2: store imported static qualifiers in dispatch receiver field

This is a partial revert of commit 104fd4c1
#KT-55116 Fixed
This commit is contained in:
Mikhail Glukhikh
2023-01-16 15:57:08 +01:00
committed by Space Team
parent 416d4f57eb
commit aafde418cc
11 changed files with 34 additions and 65 deletions
@@ -1,4 +1,4 @@
FILE: main.kt
public final fun test(list: R|kotlin/collections/List<kotlin/String>|, string: R|kotlin/String|): R|kotlin/Unit| {
R|/Matchers.assertThat|<R|ft<kotlin/collections/List<kotlin/String>, kotlin/collections/List<kotlin/String>?>|>(R|<local>/list|, R|/Matchers.hasItem|<R|kotlin/String!|>(R|<local>/string|))
Q|Matchers|.R|/Matchers.assertThat|<R|ft<kotlin/collections/List<kotlin/String>, kotlin/collections/List<kotlin/String>?>|>(R|<local>/list|, Q|Matchers|.R|/Matchers.hasItem|<R|kotlin/String!|>(R|<local>/string|))
}
@@ -1,4 +1,4 @@
FILE: FlexiblePrimitiveOverloading.kt
public final fun foo(): R|kotlin/Unit| {
R|java/lang/Integer.getInteger|(String(text), Int(239))
Q|java/lang/Integer|.R|java/lang/Integer.getInteger|(String(text), Int(239))
}
@@ -2,8 +2,8 @@ FILE: test.kt
public final fun foo(): R|kotlin/Unit| {
lval externalsMap: R|kotlin/collections/MutableMap<java/io/File, kotlin/String?>| = R|kotlin/collections/mutableMapOf|<R|java/io/File|, R|kotlin/String?|>()
local final fun test(file: R|java/io/File|): R|kotlin/Unit| {
lval base: R|java/io/File!| = R|your/ContainerUtil.find|<R|java/io/File!|>(R|<local>/externalsMap|.R|SubstitutionOverride<kotlin/collections/MutableMap.keys: R|kotlin/collections/MutableSet<java/io/File>|>|, <L> = find@fun <anonymous>(it: R|java/io/File!|): R|kotlin/Boolean| <inline=NoInline> {
^ R|my/FileUtil.isAncestor|(R|<local>/it|, R|<local>/file|, Boolean(false))
lval base: R|java/io/File!| = Q|your/ContainerUtil|.R|your/ContainerUtil.find|<R|java/io/File!|>(R|<local>/externalsMap|.R|SubstitutionOverride<kotlin/collections/MutableMap.keys: R|kotlin/collections/MutableSet<java/io/File>|>|, <L> = find@fun <anonymous>(it: R|java/io/File!|): R|kotlin/Boolean| <inline=NoInline> {
^ Q|my/FileUtil|.R|my/FileUtil.isAncestor|(R|<local>/it|, R|<local>/file|, Boolean(false))
}
)
}
@@ -22,7 +22,8 @@ import org.jetbrains.kotlin.fir.types.isUnit
object FirStandaloneQualifierChecker : FirResolvedQualifierChecker() {
override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) {
val lastQualifiedAccess = context.qualifiedAccessOrAnnotationCalls.lastOrNull() as? FirQualifiedAccess
if (lastQualifiedAccess?.explicitReceiver === expression) return
// Note: qualifier isn't standalone when it's in receiver (SomeClass.foo) or getClass (SomeClass::class) position
if (lastQualifiedAccess?.explicitReceiver === expression || lastQualifiedAccess?.dispatchReceiver === expression) return
val lastGetClass = context.getClassCalls.lastOrNull()
if (lastGetClass?.argument === expression) return
// Note: if it's real Unit, it will be filtered by ClassKind.OBJECT check below
@@ -225,9 +225,7 @@ private fun FirCallableSymbol<*>.toSymbolForCall(
val fakeOverrideOwnerLookupTag = when {
// Static fake overrides
isStatic -> {
fir.importedFromObjectOrStaticData?.let {
ConeClassLikeLookupTagImpl(it.objectClassId)
} ?: (explicitReceiver as? FirResolvedQualifier)?.toLookupTag()
((dispatchReceiver as? FirResolvedQualifier) ?: (explicitReceiver as? FirResolvedQualifier))?.toLookupTag()
}
// Member fake override or bound callable reference
dispatchReceiver !is FirNoReceiverExpression -> {
@@ -36,7 +36,6 @@ class Candidate(
private val baseSystem: ConstraintStorage,
override val callInfo: CallInfo,
val originScope: FirScope?,
val importedQualifierForStatic: FirExpression? = null,
val isFromCompanionObjectTypeScope: Boolean = false
) : AbstractCandidate() {
@@ -53,7 +53,6 @@ class CandidateFactory private constructor(
explicitReceiverKind: ExplicitReceiverKind,
scope: FirScope?,
dispatchReceiverValue: ReceiverValue? = null,
importedQualifierForStatic: FirExpression? = null,
givenExtensionReceiverOptions: List<ReceiverValue> = emptyList(),
objectsByName: Boolean = false
): Candidate {
@@ -69,7 +68,6 @@ class CandidateFactory private constructor(
baseSystem,
callInfo,
scope,
importedQualifierForStatic,
isFromCompanionObjectTypeScope = when (explicitReceiverKind) {
ExplicitReceiverKind.EXTENSION_RECEIVER ->
givenExtensionReceiverOptions.singleOrNull().isCandidateFromCompanionObjectTypeScope()
@@ -544,8 +544,7 @@ internal object CheckVisibility : CheckerStage() {
val visible = visibilityChecker.isVisible(
declaration,
candidate.callInfo,
dispatchReceiverValue = null,
importedQualifierForStatic = null
dispatchReceiverValue = null
)
if (!visible) {
sink.yieldDiagnostic(VisibilityError)
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.getExplicitBackingField
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
@@ -28,11 +27,10 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf
fun FirVisibilityChecker.isVisible(
declaration: FirMemberDeclaration,
callInfo: CallInfo,
dispatchReceiverValue: ReceiverValue?,
importedQualifierForStatic: FirExpression?
dispatchReceiverValue: ReceiverValue?
): Boolean {
val staticQualifierForCallable = runIf(declaration is FirCallableDeclaration && declaration.isStatic) {
val explicitReceiver = callInfo.explicitReceiver ?: importedQualifierForStatic
val explicitReceiver = callInfo.explicitReceiver ?: (dispatchReceiverValue as? ExpressionReceiverValue)?.explicitReceiver
(explicitReceiver as? FirResolvedQualifier)?.symbol?.fir as? FirRegularClass
}
return isVisible(
@@ -51,21 +49,19 @@ fun FirVisibilityChecker.isVisible(
candidate: Candidate
): Boolean {
val callInfo = candidate.callInfo
val dispatchReceiverValue = candidate.dispatchReceiverValue
val importedQualifierForStatic = candidate.importedQualifierForStatic
if (!isVisible(declaration, callInfo, dispatchReceiverValue, importedQualifierForStatic)) {
if (!isVisible(declaration, callInfo, candidate.dispatchReceiverValue)) {
val dispatchReceiverWithoutSmartCastType =
removeSmartCastTypeForAttemptToFitVisibility(dispatchReceiverValue, candidate.callInfo.session) ?: return false
removeSmartCastTypeForAttemptToFitVisibility(candidate.dispatchReceiverValue, candidate.callInfo.session) ?: return false
if (!isVisible(declaration, callInfo, dispatchReceiverWithoutSmartCastType, importedQualifierForStatic)) return false
if (!isVisible(declaration, callInfo, dispatchReceiverWithoutSmartCastType)) return false
candidate.dispatchReceiverValue = dispatchReceiverWithoutSmartCastType
}
val backingField = declaration.getBackingFieldIfApplicable()
if (backingField != null) {
candidate.hasVisibleBackingField = isVisible(backingField, callInfo, dispatchReceiverValue, importedQualifierForStatic)
candidate.hasVisibleBackingField = isVisible(backingField, callInfo, candidate.dispatchReceiverValue)
}
return true
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.fir.resolve.calls.tower
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
@@ -75,7 +74,6 @@ private class TowerScopeLevelProcessor(
override fun consumeCandidate(
symbol: FirBasedSymbol<*>,
dispatchReceiverValue: ReceiverValue?,
importedQualifierForStatic: FirExpression?,
givenExtensionReceiverOptions: List<ReceiverValue>,
scope: FirScope,
objectsByName: Boolean
@@ -87,7 +85,6 @@ private class TowerScopeLevelProcessor(
explicitReceiverKind,
scope,
dispatchReceiverValue,
importedQualifierForStatic,
givenExtensionReceiverOptions,
objectsByName
), candidateFactory.context
@@ -6,10 +6,11 @@
package org.jetbrains.kotlin.fir.resolve.calls.tower
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.ContextReceiverGroup
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isInner
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier
import org.jetbrains.kotlin.fir.resolve.*
@@ -25,7 +26,6 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.HidesMembers
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addToStdlib.runIf
enum class ProcessResult {
FOUND, SCOPE_EMPTY;
@@ -54,7 +54,6 @@ abstract class TowerScopeLevel {
fun consumeCandidate(
symbol: T,
dispatchReceiverValue: ReceiverValue?,
importedQualifierForStatic: FirExpression?,
givenExtensionReceiverOptions: List<ReceiverValue>,
scope: FirScope,
objectsByName: Boolean = false
@@ -147,7 +146,6 @@ class MemberScopeTowerLevel(
output.consumeCandidate(
symbol,
dispatchReceiverValue,
importedQualifierForStatic = null,
givenExtensionReceiverOptions = emptyList(),
scope
)
@@ -176,7 +174,7 @@ class MemberScopeTowerLevel(
val candidates = mutableListOf<MemberWithBaseScope<T>>()
for (group in overridableGroups) {
val visibleCandidates = group.filter {
visibilityChecker.isVisible(it.member.fir, callInfo, dispatchReceiverValue, importedQualifierForStatic = null)
visibilityChecker.isVisible(it.member.fir, callInfo, dispatchReceiverValue)
}
val visibleCandidatesFromSmartcast = visibleCandidates.filter { candidatesMapping.getValue(it) }
@@ -212,7 +210,6 @@ class MemberScopeTowerLevel(
output.consumeCandidate(
candidate,
dispatchReceiverValue,
importedQualifierForStatic = null,
givenExtensionReceiverOptions,
scope
)
@@ -330,26 +327,20 @@ class ScopeTowerLevel(
fun areThereExtensionReceiverOptions(): Boolean = givenExtensionReceiverOptions.isNotEmpty()
private fun FirCallableDeclaration.importedQualifierForObjectOrStatic(): FirExpression? {
val objectClassId = importedFromObjectOrStaticData?.objectClassId ?: return null
val symbol = session.symbolProvider.getClassLikeSymbolByClassId(objectClassId)
if (symbol is FirRegularClassSymbol) {
return buildResolvedQualifier {
packageFqName = objectClassId.packageFqName
relativeClassFqName = objectClassId.relativeClassName
this.symbol = symbol
}.apply {
resultType = bodyResolveComponents.typeForQualifier(this)
}
}
return null
}
private fun dispatchReceiverValue(candidate: FirCallableSymbol<*>): ReceiverValue? {
if (candidate.fir.isStatic) return null
val importedQualifierReceiver = candidate.fir.importedQualifierForObjectOrStatic()
if (importedQualifierReceiver != null) {
return ExpressionReceiverValue(importedQualifierReceiver)
candidate.fir.importedFromObjectOrStaticData?.let { data ->
val objectClassId = data.objectClassId
val symbol = session.symbolProvider.getClassLikeSymbolByClassId(objectClassId)
if (symbol is FirRegularClassSymbol) {
val resolvedQualifier = buildResolvedQualifier {
packageFqName = objectClassId.packageFqName
relativeClassFqName = objectClassId.relativeClassName
this.symbol = symbol
}.apply {
resultType = bodyResolveComponents.typeForQualifier(this)
}
return ExpressionReceiverValue(resolvedQualifier)
}
}
if (candidate !is FirBackingFieldSymbol) {
@@ -404,22 +395,14 @@ class ScopeTowerLevel(
val receiverExpected = withHideMembersOnly || areThereExtensionReceiverOptions()
if (candidateReceiverTypeRef == null == receiverExpected) return
val dispatchReceiverValue = dispatchReceiverValue(candidate)
val isStatic = candidate.fir.isStatic
val importedQualifierForStatic = runIf(isStatic) {
candidate.fir.importedQualifierForObjectOrStatic()
}
if (dispatchReceiverValue == null &&
importedQualifierForStatic == null &&
shouldSkipCandidateWithInconsistentExtensionReceiver(candidate)
) {
if (dispatchReceiverValue == null && shouldSkipCandidateWithInconsistentExtensionReceiver(candidate)) {
return
}
val unwrappedCandidate = candidate.fir.importedFromObjectOrStaticData?.original?.symbol.takeIf { !isStatic } ?: candidate
val unwrappedCandidate = candidate.fir.importedFromObjectOrStaticData?.original?.symbol ?: candidate
@Suppress("UNCHECKED_CAST")
processor.consumeCandidate(
unwrappedCandidate as T,
dispatchReceiverValue,
importedQualifierForStatic,
givenExtensionReceiverOptions,
scope
)
@@ -465,9 +448,7 @@ class ScopeTowerLevel(
scope.processClassifiersByName(info.name) {
empty = false
processor.consumeCandidate(
it,
dispatchReceiverValue = null,
importedQualifierForStatic = null,
it, dispatchReceiverValue = null,
givenExtensionReceiverOptions = emptyList(),
scope = scope,
objectsByName = true