FIR: Refactor JvmMappedScope to fix container-related tests with new builtins

This commit is contained in:
Ilya Chernikov
2021-06-02 14:35:46 +02:00
committed by TeamCityServer
parent 80a710a5c5
commit 5b677c068f
2 changed files with 33 additions and 49 deletions
@@ -10,15 +10,14 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.utils.classId
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.constructType
import org.jetbrains.kotlin.fir.resolve.symbolProvider
import org.jetbrains.kotlin.fir.resolve.wrapSubstitutionScopeIfNeed
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
import org.jetbrains.kotlin.fir.scopes.jvm.JvmMappedScope
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
fun wrapScopeWithJvmMapped(
@@ -50,10 +49,7 @@ fun wrapScopeWithJvmMapped(
} else {
// We should substitute Java type parameters with base Kotlin type parameters to match overrides properly
// It's necessary for MutableMap, which has *two* JavaMappedScope inside (one for itself and another for base Map)
(klass.symbol.constructType(
klass.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(),
false
) as ConeClassLikeType).wrapSubstitutionScopeIfNeed(
wrapSubstitutionScopeIfNeed(
useSiteSession, jvmMappedScope, klass, scopeSession,
derivedClass = klass,
)
@@ -63,3 +59,30 @@ fun wrapScopeWithJvmMapped(
declaredMemberScope
}
}
private fun wrapSubstitutionScopeIfNeed(
session: FirSession,
useSiteMemberScope: FirTypeScope,
declaration: FirClass,
builder: ScopeSession,
derivedClass: FirRegularClass
): FirTypeScope {
if (declaration.typeParameters.isEmpty()) return useSiteMemberScope
return builder.getOrBuild(declaration.symbol, PLATFORM_TYPE_PARAMETERS_SUBSTITUTION_SCOPE_KEY) {
val platformClass = session.platformClassMapper.getCorrespondingPlatformClass(declaration) ?: return@getOrBuild useSiteMemberScope
// This kind of substitution is necessary when method which is mapped from Java (e.g. Java Map.forEach)
// is called on an external type, like MyMap<String, String>,
// to determine parameter types properly (e.g. String, String instead of K, V)
val platformTypeParameters = platformClass.typeParameters
val platformSubstitution = createSubstitution(platformTypeParameters, declaration.defaultType(), session)
val substitutor = substitutorByMap(platformSubstitution, session)
FirClassSubstitutionScope(
session, useSiteMemberScope, substitutor,
dispatchReceiverTypeForSubstitutedMembers = derivedClass.defaultType(),
skipPrivateMembers = true,
)
}
}
private val PLATFORM_TYPE_PARAMETERS_SUBSTITUTION_SCOPE_KEY = scopeSessionKey<FirClassSymbol<*>, FirTypeScope>()
@@ -11,16 +11,13 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.transformers.createSubstitutionForSupertype
import org.jetbrains.kotlin.fir.symbols.ensureResolved
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.types.model.CaptureStatus
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.SmartSet
@@ -109,12 +106,6 @@ inline fun <reified ID : Any, reified FS : FirScope> scopeSessionKey(): ScopeSes
val USE_SITE = scopeSessionKey<FirClassSymbol<*>, FirTypeScope>()
data class SubstitutionScopeKey(
val type: ConeClassLikeType,
// This property is necessary. Otherwise we may have accidental matching when two classes have the same supertype
val derivedClassId: ClassId
) : ScopeSessionKey<FirClassLikeSymbol<*>, FirClassSubstitutionScope>()
/* TODO REMOVE */
fun createSubstitution(
typeParameters: List<FirTypeParameterRef>, // TODO: or really declared?
@@ -139,36 +130,6 @@ fun createSubstitution(
}.toMap()
}
fun ConeClassLikeType.wrapSubstitutionScopeIfNeed(
session: FirSession,
useSiteMemberScope: FirTypeScope,
declaration: FirClassLikeDeclaration,
builder: ScopeSession,
derivedClass: FirRegularClass
): FirTypeScope {
if (this.typeArguments.isEmpty()) return useSiteMemberScope
return builder.getOrBuild(declaration.symbol, SubstitutionScopeKey(this, derivedClass.symbol.classId)) {
val typeParameters = (declaration as? FirTypeParameterRefsOwner)?.typeParameters.orEmpty()
val originalSubstitution = createSubstitution(typeParameters, this, session)
val platformClass = session.platformClassMapper.getCorrespondingPlatformClass(declaration)
val substitutor = if (platformClass != null) {
// This kind of substitution is necessary when method which is mapped from Java (e.g. Java Map.forEach)
// is called on an external type, like MyMap<String, String>,
// to determine parameter types properly (e.g. String, String instead of K, V)
val platformTypeParameters = platformClass.typeParameters
val platformSubstitution = createSubstitution(platformTypeParameters, this, session)
substitutorByMap(originalSubstitution + platformSubstitution, session)
} else {
substitutorByMap(originalSubstitution, session)
}
FirClassSubstitutionScope(
session, useSiteMemberScope, substitutor,
dispatchReceiverTypeForSubstitutedMembers = derivedClass.defaultType(),
skipPrivateMembers = true,
)
}
}
private fun ConeClassLikeType.computePartialExpansion(
useSiteSession: FirSession,
supertypeSupplier: SupertypeSupplier