From 5b677c068f882d0e9bdab9e38e13260b5a085748 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Wed, 2 Jun 2021 14:35:46 +0200 Subject: [PATCH] FIR: Refactor JvmMappedScope to fix container-related tests with new builtins --- .../fir/resolve/scopes/JvmMappedScopes.kt | 43 ++++++++++++++----- .../kotlin/fir/resolve/SupertypeUtils.kt | 39 ----------------- 2 files changed, 33 insertions(+), 49 deletions(-) diff --git a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt index 293554ad4bc..013147d4f9f 100644 --- a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt +++ b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/resolve/scopes/JvmMappedScopes.kt @@ -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, + // 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, FirTypeScope>() + diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt index 2cc26320cb4..8c5625a063c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SupertypeUtils.kt @@ -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 scopeSessionKey(): ScopeSes val USE_SITE = scopeSessionKey, 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, FirClassSubstitutionScope>() - /* TODO REMOVE */ fun createSubstitution( typeParameters: List, // 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, - // 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