[FIR] Substitute supertypes in nested classifier scope
KT-38992
This commit is contained in:
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.transformers.createSubstitutionForSupertype
|
||||||
import org.jetbrains.kotlin.fir.typeContext
|
import org.jetbrains.kotlin.fir.typeContext
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
@@ -33,10 +34,11 @@ fun lookupSuperTypes(
|
|||||||
lookupInterfaces: Boolean,
|
lookupInterfaces: Boolean,
|
||||||
deep: Boolean,
|
deep: Boolean,
|
||||||
useSiteSession: FirSession,
|
useSiteSession: FirSession,
|
||||||
supertypeSupplier: SupertypeSupplier = SupertypeSupplier.Default
|
supertypeSupplier: SupertypeSupplier = SupertypeSupplier.Default,
|
||||||
|
substituteTypes: Boolean = false
|
||||||
): List<ConeClassLikeType> {
|
): List<ConeClassLikeType> {
|
||||||
return mutableListOf<ConeClassLikeType>().also {
|
return mutableListOf<ConeClassLikeType>().also {
|
||||||
klass.symbol.collectSuperTypes(it, mutableSetOf(), deep, lookupInterfaces, useSiteSession, supertypeSupplier)
|
klass.symbol.collectSuperTypes(it, mutableSetOf(), deep, lookupInterfaces, substituteTypes, useSiteSession, supertypeSupplier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +118,7 @@ private fun FirClassifierSymbol<*>.collectSuperTypes(
|
|||||||
visitedSymbols: MutableSet<FirClassifierSymbol<*>>,
|
visitedSymbols: MutableSet<FirClassifierSymbol<*>>,
|
||||||
deep: Boolean,
|
deep: Boolean,
|
||||||
lookupInterfaces: Boolean,
|
lookupInterfaces: Boolean,
|
||||||
|
substituteSuperTypes: Boolean,
|
||||||
useSiteSession: FirSession,
|
useSiteSession: FirSession,
|
||||||
supertypeSupplier: SupertypeSupplier
|
supertypeSupplier: SupertypeSupplier
|
||||||
) {
|
) {
|
||||||
@@ -131,14 +134,30 @@ private fun FirClassifierSymbol<*>.collectSuperTypes(
|
|||||||
if (deep)
|
if (deep)
|
||||||
superClassTypes.forEach {
|
superClassTypes.forEach {
|
||||||
if (it !is ConeClassErrorType) {
|
if (it !is ConeClassErrorType) {
|
||||||
it.lookupTag.toSymbol(useSiteSession)?.collectSuperTypes(
|
if (substituteSuperTypes) {
|
||||||
list,
|
val substitutedTypes = mutableListOf<ConeClassLikeType>()
|
||||||
visitedSymbols,
|
it.lookupTag.toSymbol(useSiteSession)?.collectSuperTypes(
|
||||||
deep,
|
substitutedTypes,
|
||||||
lookupInterfaces,
|
visitedSymbols,
|
||||||
useSiteSession,
|
deep,
|
||||||
supertypeSupplier
|
lookupInterfaces,
|
||||||
)
|
substituteSuperTypes,
|
||||||
|
useSiteSession,
|
||||||
|
supertypeSupplier
|
||||||
|
)
|
||||||
|
val substitutor = createSubstitutionForSupertype(it, useSiteSession)
|
||||||
|
substitutedTypes.mapTo(list) { superType -> substitutor.substituteOrSelf(superType) as ConeClassLikeType }
|
||||||
|
} else {
|
||||||
|
it.lookupTag.toSymbol(useSiteSession)?.collectSuperTypes(
|
||||||
|
list,
|
||||||
|
visitedSymbols,
|
||||||
|
deep,
|
||||||
|
lookupInterfaces,
|
||||||
|
substituteSuperTypes,
|
||||||
|
useSiteSession,
|
||||||
|
supertypeSupplier
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,7 +165,7 @@ private fun FirClassifierSymbol<*>.collectSuperTypes(
|
|||||||
val expansion =
|
val expansion =
|
||||||
supertypeSupplier.expansionForTypeAlias(fir)?.computePartialExpansion(useSiteSession, supertypeSupplier) ?: return
|
supertypeSupplier.expansionForTypeAlias(fir)?.computePartialExpansion(useSiteSession, supertypeSupplier) ?: return
|
||||||
expansion.lookupTag.toSymbol(useSiteSession)
|
expansion.lookupTag.toSymbol(useSiteSession)
|
||||||
?.collectSuperTypes(list, visitedSymbols, deep, lookupInterfaces, useSiteSession, supertypeSupplier)
|
?.collectSuperTypes(list, visitedSymbols, deep, lookupInterfaces, substituteSuperTypes, useSiteSession, supertypeSupplier)
|
||||||
}
|
}
|
||||||
else -> error("?!id:1")
|
else -> error("?!id:1")
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-11
@@ -5,12 +5,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.transformers
|
package org.jetbrains.kotlin.fir.resolve.transformers
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
|
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.getNestedClassifierScope
|
import org.jetbrains.kotlin.fir.resolve.providers.getNestedClassifierScope
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||||
@@ -21,8 +18,6 @@ import org.jetbrains.kotlin.fir.scopes.FirScope
|
|||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirNestedClassifierScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirNestedClassifierScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope
|
import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType
|
import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType
|
||||||
@@ -52,13 +47,17 @@ abstract class FirAbstractTreeTransformerWithSuperTypes(
|
|||||||
): CompositeTransformResult<FirStatement> {
|
): CompositeTransformResult<FirStatement> {
|
||||||
return withScopeCleanup {
|
return withScopeCleanup {
|
||||||
// ? Is it Ok to use original file session here ?
|
// ? Is it Ok to use original file session here ?
|
||||||
val superTypes = lookupSuperTypes(firClass, lookupInterfaces = false, deep = true, useSiteSession = session).asReversed()
|
val superTypes = lookupSuperTypes(
|
||||||
|
firClass,
|
||||||
|
lookupInterfaces = false,
|
||||||
|
deep = true,
|
||||||
|
substituteTypes = true,
|
||||||
|
useSiteSession = session
|
||||||
|
).asReversed()
|
||||||
for (superType in superTypes) {
|
for (superType in superTypes) {
|
||||||
session.getNestedClassifierScope(superType.lookupTag)?.let { nestedClassifierScope ->
|
session.getNestedClassifierScope(superType.lookupTag)?.let { nestedClassifierScope ->
|
||||||
val klass = superType.lookupTag.toSymbol(session)?.fir as? FirRegularClass
|
|
||||||
val mapping = klass?.typeParameters?.map { it.symbol }?.zip(superType.typeArguments.map { it as ConeKotlinType })?.toMap()
|
|
||||||
val substitutor = mapping?.let { ConeSubstitutorByMap(it) } ?: ConeSubstitutor.Empty
|
|
||||||
val scope = if (nestedClassifierScope is FirNestedClassifierScope) {
|
val scope = if (nestedClassifierScope is FirNestedClassifierScope) {
|
||||||
|
val substitutor = createSubstitutionForSupertype(superType, session)
|
||||||
FirNestedClassifierScopeWithSubstitution(nestedClassifierScope, substitutor)
|
FirNestedClassifierScopeWithSubstitution(nestedClassifierScope, substitutor)
|
||||||
} else {
|
} else {
|
||||||
nestedClassifierScope
|
nestedClassifierScope
|
||||||
@@ -93,6 +92,13 @@ private class FirNestedClassifierScopeWithSubstitution(
|
|||||||
) : FirScope() {
|
) : FirScope() {
|
||||||
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
|
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
|
||||||
val matchedClass = scope.getClassifierByName(name) ?: return
|
val matchedClass = scope.getClassifierByName(name) ?: return
|
||||||
|
val substitutor = substitutor.takeIf { matchedClass.fir.isInner } ?: ConeSubstitutor.Empty
|
||||||
processor(matchedClass, substitutor)
|
processor(matchedClass, substitutor)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createSubstitutionForSupertype(superType: ConeLookupTagBasedType, session: FirSession): ConeSubstitutor {
|
||||||
|
val klass = superType.lookupTag.toSymbol(session)?.fir as? FirRegularClass ?: return ConeSubstitutor.Empty
|
||||||
|
val mapping = klass.typeParameters.map { it.symbol }.zip(superType.typeArguments.map { it as ConeKotlinType }).toMap()
|
||||||
|
return ConeSubstitutorByMap(mapping)
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user