diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConstructorProcessing.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConstructorProcessing.kt index 6beee51d0b3..368d370b7ee 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConstructorProcessing.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ConstructorProcessing.kt @@ -6,9 +6,7 @@ package org.jetbrains.kotlin.fir.resolve.calls import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirConstructor -import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.declarations.FirTypeParameter +import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.impl.FirConstructorImpl import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl import org.jetbrains.kotlin.fir.resolve.* @@ -133,14 +131,13 @@ private fun processConstructors( } private class TypeAliasConstructorsSubstitutingScope( - private val typeAliasSymbol: FirTypeAliasSymbol, - private val substitutor: ConeSubstitutor, + private val typeAliasConstructorsSubstitutor: TypeAliasConstructorsSubstitutor, private val delegatingScope: FirScope ) : FirScope() { override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction { return delegatingScope.processFunctionsByName(name) { val toProcess = if (it is FirConstructorSymbol) { - it.fir.createTypeAliasConstructor(substitutor, typeAliasSymbol.fir.typeParameters).symbol + typeAliasConstructorsSubstitutor.substitute(it.fir).symbol } else { it } @@ -150,12 +147,81 @@ private class TypeAliasConstructorsSubstitutingScope( } } +private typealias ConstructorCopyFactory = F.(FirTypeRef, List, List) -> F + +private class TypeAliasConstructorsSubstitutor>( + private val typeAliasSymbol: FirTypeAliasSymbol, + private val substitutor: ConeSubstitutor, + private val copyFactory: ConstructorCopyFactory +) { + 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( typeAliasSymbol: FirTypeAliasSymbol, expandedType: ConeClassLikeType, session: FirSession, delegatingScope: FirScope ): FirScope? { + val typeAliasConstructorsSubstitutor = + prepareSubstitutorForTypeAliasConstructors( + 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 > prepareSubstitutorForTypeAliasConstructors( + typeAliasSymbol: FirTypeAliasSymbol, + expandedType: ConeClassLikeType, + session: FirSession, + copyFactory: ConstructorCopyFactory +): TypeAliasConstructorsSubstitutor? { val expandedClass = expandedType.lookupTag.toSymbol(session)?.fir as? FirRegularClass ?: return null val resultingTypeArguments = expandedType.typeArguments.map { @@ -168,45 +234,7 @@ private fun prepareSubstitutingScopeForTypeAliasConstructors( expandedClass.typeParameters.map { it.symbol }.zip(resultingTypeArguments).toMap() ); - return TypeAliasConstructorsSubstitutingScope(typeAliasSymbol, substitutor, delegatingScope) -} - -private fun FirConstructor.createTypeAliasConstructor( - substitutor: ConeSubstitutor, - typeParameters: List -): 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 - } + return TypeAliasConstructorsSubstitutor(typeAliasSymbol, substitutor, copyFactory) } private fun FirTypeRef.substitute(substitutor: ConeSubstitutor): FirResolvedTypeRef? =