[FIR2IR] Cleanup and reuse utility for creating substitutor from call

This commit is contained in:
Dmitriy Novozhilov
2023-11-09 10:50:34 +02:00
committed by Space Team
parent 5f5daa0e06
commit aa1a997f8a
3 changed files with 19 additions and 27 deletions
@@ -33,6 +33,8 @@ import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.FirSimpleSyntheticPropertySymbol
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
import org.jetbrains.kotlin.fir.scopes.impl.originalConstructorIfTypeAlias
@@ -857,3 +859,18 @@ internal fun implicitCast(original: IrExpression, castType: IrType, typeOperator
}
return implicitCast(original.argument, castType, typeOperator)
}
context(Fir2IrComponents)
internal fun FirQualifiedAccessExpression.buildSubstitutorByCalledCallable(): ConeSubstitutor {
val typeParameters = when (val declaration = calleeReference.toResolvedCallableSymbol()?.fir) {
is FirFunction -> declaration.typeParameters
is FirProperty -> declaration.typeParameters
else -> return ConeSubstitutor.Empty
}
val map = mutableMapOf<FirTypeParameterSymbol, ConeKotlinType>()
for ((index, typeParameter) in typeParameters.withIndex()) {
val typeProjection = typeArguments.getOrNull(index) as? FirTypeProjectionWithVariance ?: continue
map[typeParameter.symbol] = typeProjection.typeRef.coneType
}
return ConeSubstitutorByMap(map, session)
}
@@ -313,7 +313,7 @@ class Fir2IrImplicitCastInserter(
}
receiver === extensionReceiver -> {
val extensionReceiverType = referencedDeclaration?.receiverParameter?.typeRef?.coneType ?: return null
val substitutor = createSubstitutorFromTypeArguments(selector, referencedDeclaration)
val substitutor = selector.buildSubstitutorByCalledCallable()
val substitutedType = substitutor.substituteOrSelf(extensionReceiverType)
// Frontend may write captured types as type arguments (by design), so we need to approximate receiver type after substitution
val approximatedType = session.typeApproximator.approximateToSuperType(
@@ -334,20 +334,6 @@ class Fir2IrImplicitCastInserter(
return null
}
private fun createSubstitutorFromTypeArguments(
qualifiedAccessExpression: FirQualifiedAccessExpression,
callableDeclaration: FirCallableDeclaration,
): ConeSubstitutor {
if (qualifiedAccessExpression.typeArguments.isEmpty() || callableDeclaration.typeParameters.isEmpty()) return ConeSubstitutor.Empty
val map = buildMap {
for ((parameter, argument) in callableDeclaration.typeParameters.zip(qualifiedAccessExpression.typeArguments)) {
val argumentType = argument.toConeTypeProjection().type ?: continue
put(parameter.symbol, argumentType)
}
}
return ConeSubstitutorByMap(map, session)
}
private fun implicitCastOrExpression(
original: IrExpression, castType: ConeKotlinType, typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT
): IrExpression {
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.fir.resolve.calls.FirSimpleSyntheticPropertySymbol
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
import org.jetbrains.kotlin.fir.resolve.calls.getExpectedType
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.approximateDeclarationType
import org.jetbrains.kotlin.fir.scopes.getDeclaredConstructors
import org.jetbrains.kotlin.fir.scopes.impl.originalConstructorIfTypeAlias
@@ -839,16 +838,6 @@ class CallAndReferenceGenerator(
}
}
private fun FirFunctionCall.buildSubstitutorByCalledFunction(function: FirFunction?): ConeSubstitutor? {
if (function == null) return null
val map = mutableMapOf<FirTypeParameterSymbol, ConeKotlinType>()
for ((index, typeParameter) in function.typeParameters.withIndex()) {
val typeProjection = typeArguments.getOrNull(index) as? FirTypeProjectionWithVariance ?: continue
map[typeParameter.symbol] = typeProjection.typeRef.coneType
}
return ConeSubstitutorByMap(map, session)
}
private fun extractArgumentsMapping(
call: FirCall,
): Triple<List<FirValueParameter>?, Map<FirExpression, FirValueParameter>?, ConeSubstitutor> {
@@ -861,7 +850,7 @@ class CallAndReferenceGenerator(
val function = ((calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirFunctionSymbol<*>)?.fir
val valueParameters = function?.valueParameters
val argumentMapping = call.resolvedArgumentMapping
val substitutor = (call as? FirFunctionCall)?.buildSubstitutorByCalledFunction(function) ?: ConeSubstitutor.Empty
val substitutor = (call as? FirFunctionCall)?.buildSubstitutorByCalledCallable() ?: ConeSubstitutor.Empty
return Triple(valueParameters, argumentMapping, substitutor)
}