FIR: Abstract parts for type alias constructors resolution

It's necessary to support combination of type aliases + SAM
This commit is contained in:
Denis Zharkov
2019-11-27 13:09:53 +03:00
parent fbe7db5471
commit ae01d050c9
@@ -6,9 +6,7 @@
package org.jetbrains.kotlin.fir.resolve.calls 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.FirConstructor import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.impl.FirConstructorImpl import org.jetbrains.kotlin.fir.declarations.impl.FirConstructorImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.*
@@ -133,14 +131,13 @@ private fun processConstructors(
} }
private class TypeAliasConstructorsSubstitutingScope( private class TypeAliasConstructorsSubstitutingScope(
private val typeAliasSymbol: FirTypeAliasSymbol, private val typeAliasConstructorsSubstitutor: TypeAliasConstructorsSubstitutor<FirConstructor>,
private val substitutor: ConeSubstitutor,
private val delegatingScope: FirScope private val delegatingScope: FirScope
) : FirScope() { ) : FirScope() {
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction { override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction {
return delegatingScope.processFunctionsByName(name) { return delegatingScope.processFunctionsByName(name) {
val toProcess = if (it is FirConstructorSymbol) { val toProcess = if (it is FirConstructorSymbol) {
it.fir.createTypeAliasConstructor(substitutor, typeAliasSymbol.fir.typeParameters).symbol typeAliasConstructorsSubstitutor.substitute(it.fir).symbol
} else { } else {
it it
} }
@@ -150,12 +147,81 @@ private class TypeAliasConstructorsSubstitutingScope(
} }
} }
private typealias ConstructorCopyFactory<F> = F.(FirTypeRef, List<FirValueParameter>, List<FirTypeParameter>) -> F
private class TypeAliasConstructorsSubstitutor<F : FirMemberFunction<F>>(
private val typeAliasSymbol: FirTypeAliasSymbol,
private val substitutor: ConeSubstitutor,
private val copyFactory: ConstructorCopyFactory<F>
) {
fun substitute(baseFunction: F): F {
val typeParameters = typeAliasSymbol.fir.typeParameters
val newReturnTypeRef = baseFunction.returnTypeRef.substitute(substitutor)
val newParameterTypeRefs = baseFunction.valueParameters.map { valueParameter ->
valueParameter.returnTypeRef.substitute(substitutor)
}
if (newReturnTypeRef == null && newParameterTypeRefs.all { it == null }) return baseFunction
return baseFunction.copyFactory(
newReturnTypeRef ?: baseFunction.returnTypeRef,
baseFunction.valueParameters.zip(
newParameterTypeRefs
) { valueParameter, newTypeRef ->
with(valueParameter) {
FirValueParameterImpl(
source,
session,
newTypeRef ?: returnTypeRef,
name,
FirVariableSymbol(valueParameter.symbol.callableId),
defaultValue,
isCrossinline,
isNoinline,
isVararg
)
}
},
typeParameters
)
}
}
private fun prepareSubstitutingScopeForTypeAliasConstructors( private fun prepareSubstitutingScopeForTypeAliasConstructors(
typeAliasSymbol: FirTypeAliasSymbol, typeAliasSymbol: FirTypeAliasSymbol,
expandedType: ConeClassLikeType, expandedType: ConeClassLikeType,
session: FirSession, session: FirSession,
delegatingScope: FirScope delegatingScope: FirScope
): FirScope? { ): FirScope? {
val typeAliasConstructorsSubstitutor =
prepareSubstitutorForTypeAliasConstructors<FirConstructor>(
typeAliasSymbol,
expandedType,
session
) factory@{ newReturnTypeRef, newValueParameters, newTypeParameters ->
FirConstructorImpl(
source, session, newReturnTypeRef, receiverTypeRef, status,
FirConstructorSymbol(symbol.callableId, overriddenSymbol = symbol)
).apply {
resolvePhase = this@factory.resolvePhase
valueParameters += newValueParameters
this.typeParameters += newTypeParameters
}
} ?: return null
return TypeAliasConstructorsSubstitutingScope(
typeAliasConstructorsSubstitutor,
delegatingScope
)
}
private fun <F : FirMemberFunction<F>> prepareSubstitutorForTypeAliasConstructors(
typeAliasSymbol: FirTypeAliasSymbol,
expandedType: ConeClassLikeType,
session: FirSession,
copyFactory: ConstructorCopyFactory<F>
): 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 {
@@ -168,45 +234,7 @@ private fun prepareSubstitutingScopeForTypeAliasConstructors(
expandedClass.typeParameters.map { it.symbol }.zip(resultingTypeArguments).toMap() expandedClass.typeParameters.map { it.symbol }.zip(resultingTypeArguments).toMap()
); );
return TypeAliasConstructorsSubstitutingScope(typeAliasSymbol, substitutor, delegatingScope) return TypeAliasConstructorsSubstitutor(typeAliasSymbol, substitutor, copyFactory)
}
private fun FirConstructor.createTypeAliasConstructor(
substitutor: ConeSubstitutor,
typeParameters: List<FirTypeParameter>
): FirConstructor {
val newReturnTypeRef = returnTypeRef.substitute(substitutor)
val newParameterTypeRefs = valueParameters.map { valueParameter ->
valueParameter.returnTypeRef.substitute(substitutor)
}
if (newReturnTypeRef == null && newParameterTypeRefs.all { it == null }) return this
return FirConstructorImpl(
source, session, newReturnTypeRef ?: returnTypeRef, receiverTypeRef, status,
FirConstructorSymbol(symbol.callableId, overriddenSymbol = symbol)
).apply {
resolvePhase = this@createTypeAliasConstructor.resolvePhase
valueParameters += this@createTypeAliasConstructor.valueParameters.zip(
newParameterTypeRefs
) { valueParameter, newTypeRef ->
with(valueParameter) {
FirValueParameterImpl(
source,
session,
newTypeRef ?: returnTypeRef,
name,
FirVariableSymbol(valueParameter.symbol.callableId),
defaultValue,
isCrossinline,
isNoinline,
isVararg
)
}
}
this.typeParameters += typeParameters
}
} }
private fun FirTypeRef.substitute(substitutor: ConeSubstitutor): FirResolvedTypeRef? = private fun FirTypeRef.substitute(substitutor: ConeSubstitutor): FirResolvedTypeRef? =