FIR: Simplify ConstructorProcessing relevant to type aliases

This commit is contained in:
Denis Zharkov
2020-10-30 14:27:42 +03:00
parent 8a949b0dcf
commit f9aab77ce5
@@ -8,12 +8,13 @@ package org.jetbrains.kotlin.fir.resolve.calls
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.declarations.builder.buildConstructedClassTypeParameterRef import org.jetbrains.kotlin.fir.declarations.builder.buildConstructedClassTypeParameterRef
import org.jetbrains.kotlin.fir.declarations.builder.buildConstructor
import org.jetbrains.kotlin.fir.declarations.builder.buildConstructorCopy import org.jetbrains.kotlin.fir.declarations.builder.buildConstructorCopy
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
@@ -118,21 +119,27 @@ private fun FirTypeAliasSymbol.findSAMConstructorForTypeAlias(
val namedSymbol = samConstructorForClass.symbol as? FirNamedFunctionSymbol ?: return null val namedSymbol = samConstructorForClass.symbol as? FirNamedFunctionSymbol ?: return null
val substitutor = prepareSubstitutorForTypeAliasConstructors<FirSimpleFunction>( val substitutor = prepareSubstitutorForTypeAliasConstructors(
this,
type, type,
session session
) { newReturnType, newParameterTypes, newTypeParameters -> ) ?: return null
FirFakeOverrideGenerator.createFakeOverrideFunction(
session, this, namedSymbol,
newDispatchReceiverType = null,
newReceiverType = null,
newReturnType, newParameterTypes, newTypeParameters,
expansionRegularClass.classId,
).fir
} ?: return null
return substitutor.substitute(samConstructorForClass) val typeParameters = this@findSAMConstructorForTypeAlias.fir.typeParameters
val newReturnType = samConstructorForClass.returnTypeRef.coneType.let(substitutor::substituteOrNull)
val newParameterTypes = samConstructorForClass.valueParameters.map { valueParameter ->
valueParameter.returnTypeRef.coneType.let(substitutor::substituteOrNull)
}
if (newReturnType == null && newParameterTypes.all { it == null }) return samConstructorForClass
return FirFakeOverrideGenerator.createFakeOverrideFunction(
session, samConstructorForClass, namedSymbol,
newDispatchReceiverType = null,
newReceiverType = null,
newReturnType, newParameterTypes, typeParameters,
expansionRegularClass.classId,
).fir
} }
private fun processConstructors( private fun processConstructors(
@@ -152,9 +159,10 @@ private fun processConstructors(
val basicScope = type.scope(session, bodyResolveComponents.scopeSession, FakeOverrideTypeCalculator.DoNothing) val basicScope = type.scope(session, bodyResolveComponents.scopeSession, FakeOverrideTypeCalculator.DoNothing)
if (basicScope != null && type.typeArguments.isNotEmpty()) { if (basicScope != null && type.typeArguments.isNotEmpty()) {
prepareSubstitutingScopeForTypeAliasConstructors( TypeAliasConstructorsSubstitutingScope(
matchedSymbol, session, basicScope matchedSymbol,
) ?: return basicScope
)
} else basicScope } else basicScope
} }
is FirClassSymbol -> is FirClassSymbol ->
@@ -179,110 +187,31 @@ private fun processConstructors(
private class TypeAliasConstructorsSubstitutingScope( private class TypeAliasConstructorsSubstitutingScope(
private val typeAliasSymbol: FirTypeAliasSymbol, private val typeAliasSymbol: FirTypeAliasSymbol,
private val copyFactory: ConstructorCopyFactory<FirConstructor>,
private val delegatingScope: FirScope private val delegatingScope: FirScope
) : FirScope() { ) : FirScope() {
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) { override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
delegatingScope.processDeclaredConstructors { delegatingScope.processDeclaredConstructors { originalConstructorSymbol ->
val typeParameters = typeAliasSymbol.fir.typeParameters val typeParameters = typeAliasSymbol.fir.typeParameters
if (typeParameters.isEmpty()) processor(it) if (typeParameters.isEmpty()) processor(originalConstructorSymbol)
else { else {
processor(it.fir.copyFactory( processor(
null, buildConstructorCopy(originalConstructorSymbol.fir) {
null, symbol = FirConstructorSymbol(originalConstructorSymbol.callableId, overriddenSymbol = originalConstructorSymbol)
typeParameters.map { buildConstructedClassTypeParameterRef { symbol = it.symbol } } origin = FirDeclarationOrigin.SubstitutionOverride
).symbol) this.typeParameters += typeParameters.map { buildConstructedClassTypeParameterRef { symbol = it.symbol } }
}.symbol
)
} }
} }
} }
} }
private typealias ConstructorCopyFactory2<F> = private fun prepareSubstitutorForTypeAliasConstructors(
F.(newReturnType: ConeKotlinType?, newValueParameterTypes: List<ConeKotlinType?>?, newTypeParameters: List<FirTypeParameter>) -> F
private typealias ConstructorCopyFactory<F> =
F.(newReturnType: ConeKotlinType?, newValueParameterTypes: List<ConeKotlinType?>?, newTypeParameters: List<FirTypeParameterRef>) -> F
private class TypeAliasConstructorsSubstitutor<F : FirFunction<F>>(
private val typeAliasSymbol: FirTypeAliasSymbol,
private val substitutor: ConeSubstitutor,
private val copyFactory: ConstructorCopyFactory2<F>
) {
fun substitute(baseFunction: F): F {
val typeParameters = typeAliasSymbol.fir.typeParameters
val newReturnType = baseFunction.returnTypeRef.coneType.let(substitutor::substituteOrNull)
val newParameterTypes = baseFunction.valueParameters.map { valueParameter ->
valueParameter.returnTypeRef.coneType.let(substitutor::substituteOrNull)
}
if (newReturnType == null && newParameterTypes.all { it == null }) return baseFunction
return baseFunction.copyFactory(
newReturnType,
newParameterTypes,
typeParameters
)
}
}
private fun prepareSubstitutingScopeForTypeAliasConstructors(
typeAliasSymbol: FirTypeAliasSymbol,
session: FirSession,
delegatingScope: FirScope
): FirScope {
val copyFactory2: ConstructorCopyFactory<FirConstructor> = factory@{ newReturnType, newParameterTypes, newTypeParameters ->
buildConstructor {
source = this@factory.source
this.session = session
origin = FirDeclarationOrigin.SubstitutionOverride
returnTypeRef = this@factory.returnTypeRef.withReplacedConeType(newReturnType)
receiverTypeRef = this@factory.receiverTypeRef
status = this@factory.status
symbol = FirConstructorSymbol(this@factory.symbol.callableId, overriddenSymbol = this@factory.symbol)
resolvePhase = this@factory.resolvePhase
if (newParameterTypes != null) {
valueParameters +=
this@factory.valueParameters.zip(
newParameterTypes
) { valueParameter, newParameterType ->
buildValueParameter {
source = valueParameter.source
this.session = session
resolvePhase = valueParameter.resolvePhase
origin = FirDeclarationOrigin.SubstitutionOverride
returnTypeRef = valueParameter.returnTypeRef.withReplacedConeType(newParameterType)
name = valueParameter.name
symbol = FirVariableSymbol(valueParameter.symbol.callableId)
defaultValue = valueParameter.defaultValue
isCrossinline = valueParameter.isCrossinline
isNoinline = valueParameter.isNoinline
isVararg = valueParameter.isVararg
}
}
} else {
valueParameters += this@factory.valueParameters
}
this.typeParameters += newTypeParameters
this.attributes = this@factory.attributes.copy()
}
}
return TypeAliasConstructorsSubstitutingScope(
typeAliasSymbol,
copyFactory2,
delegatingScope
)
}
private fun <F : FirFunction<F>> prepareSubstitutorForTypeAliasConstructors(
typeAliasSymbol: FirTypeAliasSymbol,
expandedType: ConeClassLikeType, expandedType: ConeClassLikeType,
session: FirSession, session: FirSession
copyFactory: ConstructorCopyFactory2<F> ): ConeSubstitutor? {
): TypeAliasConstructorsSubstitutor<F>? {
val expandedClass = expandedType.lookupTag.toSymbol(session)?.fir as? FirRegularClass ?: return null val expandedClass = expandedType.lookupTag.toSymbol(session)?.fir as? FirRegularClass ?: return null
val resultingTypeArguments = expandedType.typeArguments.map { val resultingTypeArguments = expandedType.typeArguments.map {
@@ -290,12 +219,9 @@ private fun <F : FirFunction<F>> prepareSubstitutorForTypeAliasConstructors(
// typealias A = ArrayList<*>() // typealias A = ArrayList<*>()
it as? ConeKotlinType ?: return null it as? ConeKotlinType ?: return null
} }
return substitutorByMap(
val substitutor = substitutorByMap(
expandedClass.typeParameters.map { it.symbol }.zip(resultingTypeArguments).toMap() expandedClass.typeParameters.map { it.symbol }.zip(resultingTypeArguments).toMap()
) )
return TypeAliasConstructorsSubstitutor(typeAliasSymbol, substitutor, copyFactory)
} }
private fun prepareCopyConstructorForTypealiasNestedClass( private fun prepareCopyConstructorForTypealiasNestedClass(
@@ -341,4 +267,5 @@ private fun prepareCopyConstructorForTypealiasNestedClass(
} }
private object TypeAliasConstructorKey : FirDeclarationDataKey() private object TypeAliasConstructorKey : FirDeclarationDataKey()
var FirConstructor.originalConstructorIfTypeAlias: FirConstructor? by FirDeclarationDataRegistry.data(TypeAliasConstructorKey) var FirConstructor.originalConstructorIfTypeAlias: FirConstructor? by FirDeclarationDataRegistry.data(TypeAliasConstructorKey)