diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt index 2c00ef83086..5bbe95254e7 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenProperties -import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope +import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.PossiblyFirFakeOverrideSymbol @@ -84,7 +84,7 @@ class FakeOverrideGenerator( declarationStorage::getCachedIrFunction, declarationStorage::createIrFunction, createFakeOverrideSymbol = { firFunction, callableSymbol -> - FirClassSubstitutionScope.createFakeOverrideFunction( + FirFakeOverrideGenerator.createFakeOverrideFunction( session, firFunction, callableSymbol, derivedClassId = klass.symbol.classId, isExpect = (klass as? FirRegularClass)?.isExpect == true @@ -107,7 +107,7 @@ class FakeOverrideGenerator( declarationStorage::getCachedIrProperty, declarationStorage::createIrProperty, createFakeOverrideSymbol = { firProperty, callableSymbol -> - FirClassSubstitutionScope.createFakeOverrideProperty( + FirFakeOverrideGenerator.createFakeOverrideProperty( session, firProperty, callableSymbol, derivedClassId = klass.symbol.classId, isExpect = (klass as? FirRegularClass)?.isExpect == true 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 54326503fa2..24f45247b0f 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 @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved import org.jetbrains.kotlin.fir.scopes.FirScope -import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope +import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator import org.jetbrains.kotlin.fir.scopes.scopeForClass import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* @@ -122,7 +122,7 @@ private fun FirTypeAliasSymbol.findSAMConstructorForTypeAlias( type, session ) { newReturnType, newParameterTypes, newTypeParameters -> - FirClassSubstitutionScope.createFakeOverrideFunction( + FirFakeOverrideGenerator.createFakeOverrideFunction( session, this, namedSymbol, null, newReturnType, newParameterTypes, newTypeParameters ).fir diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt index 8d13eb9d6dd..1f20b82a07b 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt @@ -5,26 +5,18 @@ package org.jetbrains.kotlin.fir.scopes.impl -import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.* -import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty -import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty -import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.chain import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction -import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* -import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef -import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name @@ -149,7 +141,7 @@ class FirClassSubstitutionScope( * it's safe to cast newTypeParameters to List */ @Suppress("UNCHECKED_CAST") - return createFakeOverrideFunction( + return FirFakeOverrideGenerator.createFakeOverrideFunction( session, member, original, @@ -174,7 +166,7 @@ class FirClassSubstitutionScope( if (newReturnType == null && newParameterTypes.all { it == null } && newTypeParameters === constructor.typeParameters) { return original } - return createFakeOverrideConstructor( + return FirFakeOverrideGenerator.createFakeOverrideConstructor( FirConstructorSymbol(original.callableId, overriddenSymbol = original), session, constructor, newReturnType, newParameterTypes, newTypeParameters, makeExpect ).symbol @@ -193,7 +185,7 @@ class FirClassSubstitutionScope( } @Suppress("UNCHECKED_CAST") - return createFakeOverrideProperty( + return FirFakeOverrideGenerator.createFakeOverrideProperty( session, member, original, @@ -213,7 +205,7 @@ class FirClassSubstitutionScope( ) private fun createSubstitutedData(member: FirCallableMemberDeclaration<*>): SubstitutedData { - val (newTypeParameters, substitutor) = createNewTypeParametersAndSubstitutor( + val (newTypeParameters, substitutor) = FirFakeOverrideGenerator.createNewTypeParametersAndSubstitutor( member as FirTypeParameterRefsOwner, substitutor, forceTypeParametersRecreation = derivedClassId != null && derivedClassId != member.symbol.callableId.classId @@ -235,7 +227,7 @@ class FirClassSubstitutionScope( val returnType = member.returnTypeRef.coneType val newReturnType = returnType.substitute() ?: return original - return createFakeOverrideField(session, member, original, newReturnType, derivedClassId) + return FirFakeOverrideGenerator.createFakeOverrideField(session, member, original, newReturnType, derivedClassId) } private fun createFakeOverrideAccessor(original: FirAccessorSymbol): FirAccessorSymbol { @@ -254,403 +246,7 @@ class FirClassSubstitutionScope( return original } - return createFakeOverrideAccessor(session, member, original, newReturnType, newParameterTypes) - } - - companion object { - fun createFakeOverrideFunction( - session: FirSession, - baseFunction: FirSimpleFunction, - baseSymbol: FirNamedFunctionSymbol, - newReceiverType: ConeKotlinType? = null, - newReturnType: ConeKotlinType? = null, - newParameterTypes: List? = null, - newTypeParameters: List? = null, - derivedClassId: ClassId? = null, - isExpect: Boolean = baseFunction.isExpect - ): FirNamedFunctionSymbol { - val symbol = FirNamedFunctionSymbol( - CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseFunction.name), - isFakeOverride = true, overriddenSymbol = baseSymbol - ) - createFakeOverrideFunction( - symbol, session, baseFunction, newReceiverType, newReturnType, newParameterTypes, newTypeParameters, isExpect - ) - return symbol - } - - private fun createFakeOverrideFunction( - fakeOverrideSymbol: FirFunctionSymbol, - session: FirSession, - baseFunction: FirSimpleFunction, - newReceiverType: ConeKotlinType?, - newReturnType: ConeKotlinType?, - newParameterTypes: List?, - newTypeParameters: List?, - isExpect: Boolean = baseFunction.isExpect, - ): FirSimpleFunction { - // TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl - // As second alternative, we can invent some light-weight kind of FirRegularClass - return createCopyForFirFunction( - fakeOverrideSymbol, - baseFunction, - session, - FirDeclarationOrigin.FakeOverride, - isExpect, - newParameterTypes, - newTypeParameters, - newReceiverType, - newReturnType - ) - } - - fun createCopyForFirFunction( - newSymbol: FirFunctionSymbol, - baseFunction: FirSimpleFunction, - session: FirSession, - origin: FirDeclarationOrigin, - isExpect: Boolean = baseFunction.isExpect, - newParameterTypes: List? = null, - newTypeParameters: List? = null, - newReceiverType: ConeKotlinType? = null, - newReturnType: ConeKotlinType? = null, - newModality: Modality? = null, - newVisibility: Visibility? = null, - ): FirSimpleFunction { - return buildSimpleFunction { - source = baseFunction.source - this.session = session - this.origin = origin - name = baseFunction.name - status = baseFunction.status.updatedStatus(isExpect, newModality, newVisibility) - symbol = newSymbol - resolvePhase = baseFunction.resolvePhase - - typeParameters += configureAnnotationsTypeParametersAndSignature( - session, baseFunction, newParameterTypes, newTypeParameters, newReceiverType, newReturnType - ).filterIsInstance() - } - } - - private fun createFakeOverrideConstructor( - fakeOverrideSymbol: FirConstructorSymbol, - session: FirSession, - baseConstructor: FirConstructor, - newReturnType: ConeKotlinType?, - newParameterTypes: List?, - newTypeParameters: List?, - isExpect: Boolean - ): FirConstructor { - // TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl - // As second alternative, we can invent some light-weight kind of FirRegularClass - return buildConstructor { - source = baseConstructor.source - this.session = session - origin = FirDeclarationOrigin.FakeOverride - receiverTypeRef = baseConstructor.receiverTypeRef?.withReplacedConeType(null) - status = baseConstructor.status.updatedStatus(isExpect) - symbol = fakeOverrideSymbol - resolvePhase = baseConstructor.resolvePhase - - typeParameters += configureAnnotationsTypeParametersAndSignature( - session, baseConstructor, newParameterTypes, newTypeParameters, newReceiverType = null, newReturnType - ) - } - } - - private fun FirFunctionBuilder.configureAnnotationsTypeParametersAndSignature( - session: FirSession, - baseFunction: FirFunction<*>, - newParameterTypes: List?, - newTypeParameters: List?, - newReceiverType: ConeKotlinType?, - newReturnType: ConeKotlinType? - ): List { - return when { - baseFunction.typeParameters.isEmpty() -> { - configureAnnotationsAndSignature(session, baseFunction, newParameterTypes, newReceiverType, newReturnType) - emptyList() - } - newTypeParameters == null -> { - val (copiedTypeParameters, substitutor) = createNewTypeParametersAndSubstitutor( - baseFunction, ConeSubstitutor.Empty - ) - val copiedParameterTypes = baseFunction.valueParameters.map { - substitutor.substituteOrNull(it.returnTypeRef.coneType) - } - val (copiedReceiverType, copiedReturnType) = substituteReceiverAndReturnType( - baseFunction as FirCallableMemberDeclaration<*>, newReceiverType, newReturnType, substitutor - ) - configureAnnotationsAndSignature(session, baseFunction, copiedParameterTypes, copiedReceiverType, copiedReturnType) - copiedTypeParameters - } - else -> { - configureAnnotationsAndSignature(session, baseFunction, newParameterTypes, newReceiverType, newReturnType) - newTypeParameters - } - } - } - - private fun FirFunctionBuilder.configureAnnotationsAndSignature( - session: FirSession, - baseFunction: FirFunction<*>, - newParameterTypes: List?, - newReceiverType: ConeKotlinType?, - newReturnType: ConeKotlinType? - ) { - annotations += baseFunction.annotations - returnTypeRef = replaceReturnTypeIfResolved(baseFunction, newReturnType) - - if (this is FirSimpleFunctionBuilder) { - receiverTypeRef = baseFunction.receiverTypeRef?.withReplacedConeType(newReceiverType) - } - valueParameters += baseFunction.valueParameters.zip( - newParameterTypes ?: List(baseFunction.valueParameters.size) { null } - ) { valueParameter, newType -> - buildValueParameterCopy(valueParameter) { - origin = FirDeclarationOrigin.FakeOverride - returnTypeRef = valueParameter.returnTypeRef.withReplacedConeType(newType) - symbol = FirVariableSymbol(valueParameter.symbol.callableId) - } - } - } - - private fun replaceReturnTypeIfResolved( - base: FirCallableDeclaration<*>, - newReturnType: ConeKotlinType? - ): FirTypeRef = if (base.returnTypeRef is FirResolvedTypeRef) - base.returnTypeRef.withReplacedConeType(newReturnType) - else - base.returnTypeRef - - fun createFakeOverrideProperty( - session: FirSession, - baseProperty: FirProperty, - baseSymbol: FirPropertySymbol, - newReceiverType: ConeKotlinType? = null, - newReturnType: ConeKotlinType? = null, - newTypeParameters: List? = null, - derivedClassId: ClassId? = null, - isExpect: Boolean = baseProperty.isExpect - ): FirPropertySymbol { - val symbol = FirPropertySymbol( - CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseProperty.name), - isFakeOverride = true, overriddenSymbol = baseSymbol - ) - createCopyForFirProperty( - symbol, baseProperty, session, isExpect, - newTypeParameters, newReceiverType, newReturnType - ) - return symbol - } - - fun createCopyForFirProperty( - newSymbol: FirPropertySymbol, - baseProperty: FirProperty, - session: FirSession, - isExpect: Boolean = baseProperty.isExpect, - newTypeParameters: List? = null, - newReceiverType: ConeKotlinType? = null, - newReturnType: ConeKotlinType? = null, - newModality: Modality? = null, - newVisibility: Visibility? = null, - ): FirProperty { - return buildProperty { - source = baseProperty.source - this.session = session - origin = FirDeclarationOrigin.FakeOverride - name = baseProperty.name - isVar = baseProperty.isVar - this.symbol = newSymbol - isLocal = false - status = baseProperty.status.updatedStatus(isExpect, newModality, newVisibility) - - resolvePhase = baseProperty.resolvePhase - typeParameters += configureAnnotationsTypeParametersAndSignature( - baseProperty, - newTypeParameters, - newReceiverType, - newReturnType - ) - } - } - - private fun FirPropertyBuilder.configureAnnotationsTypeParametersAndSignature( - baseProperty: FirProperty, - newTypeParameters: List?, - newReceiverType: ConeKotlinType?, - newReturnType: ConeKotlinType? - ): List { - return when { - baseProperty.typeParameters.isEmpty() -> { - configureAnnotationsAndSignature(baseProperty, newReceiverType, newReturnType) - emptyList() - } - newTypeParameters == null -> { - val (copiedTypeParameters, substitutor) = createNewTypeParametersAndSubstitutor( - baseProperty, ConeSubstitutor.Empty - ) - val (copiedReceiverType, copiedReturnType) = substituteReceiverAndReturnType( - baseProperty, newReceiverType, newReturnType, substitutor - ) - configureAnnotationsAndSignature(baseProperty, copiedReceiverType, copiedReturnType) - copiedTypeParameters.filterIsInstance() - } - else -> { - configureAnnotationsAndSignature(baseProperty, newReceiverType, newReturnType) - newTypeParameters - } - } - } - - private fun substituteReceiverAndReturnType( - baseCallable: FirCallableMemberDeclaration<*>, - newReceiverType: ConeKotlinType?, - newReturnType: ConeKotlinType?, - substitutor: ConeSubstitutor - ): Pair { - val copiedReceiverType = newReceiverType?.let { - substitutor.substituteOrNull(it) - } ?: baseCallable.receiverTypeRef?.let { - substitutor.substituteOrNull(it.coneType) - } - val copiedReturnType = newReturnType?.let { - substitutor.substituteOrNull(it) - } ?: baseCallable.returnTypeRef.let { - substitutor.substituteOrNull(it.coneType) - } - return copiedReceiverType to copiedReturnType - } - - private fun FirPropertyBuilder.configureAnnotationsAndSignature( - baseProperty: FirProperty, - newReceiverType: ConeKotlinType?, - newReturnType: ConeKotlinType? - ) { - annotations += baseProperty.annotations - returnTypeRef = replaceReturnTypeIfResolved(baseProperty, newReturnType) - receiverTypeRef = baseProperty.receiverTypeRef?.withReplacedConeType(newReceiverType) - } - - private fun createFakeOverrideField( - session: FirSession, - baseField: FirField, - baseSymbol: FirFieldSymbol, - newReturnType: ConeKotlinType?, - derivedClassId: ClassId? - ): FirFieldSymbol { - val symbol = FirFieldSymbol( - CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseField.name) - ) - buildField { - source = baseField.source - this.session = session - origin = FirDeclarationOrigin.FakeOverride - resolvePhase = baseField.resolvePhase - returnTypeRef = baseField.returnTypeRef.withReplacedConeType(newReturnType) - name = baseField.name - this.symbol = symbol - isVar = baseField.isVar - status = baseField.status - resolvePhase = baseField.resolvePhase - annotations += baseField.annotations - } - return symbol - } - - fun createFakeOverrideAccessor( - session: FirSession, - baseProperty: FirSyntheticProperty, - baseSymbol: FirAccessorSymbol, - newReturnType: ConeKotlinType?, - newParameterTypes: List? - ): FirAccessorSymbol { - val functionSymbol = FirNamedFunctionSymbol(baseSymbol.accessorId) - val function = createFakeOverrideFunction( - functionSymbol, - session, - baseProperty.getter.delegate, - newReceiverType = null, - newReturnType, - newParameterTypes, - newTypeParameters = null - ) - return buildSyntheticProperty { - this.session = session - name = baseProperty.name - symbol = FirAccessorSymbol(baseSymbol.callableId, baseSymbol.accessorId) - delegateGetter = function - }.symbol - } - - private fun FirDeclarationStatus.updatedStatus( - isExpect: Boolean, - newModality: Modality? = null, - newVisibility: Visibility? = null, - ): FirDeclarationStatus { - return if (this.isExpect == isExpect && newModality == null && newVisibility == null) { - this - } else { - require(this is FirDeclarationStatusImpl) { "Unexpected class ${this::class}" } - this.resolved(newVisibility ?: visibility, newModality ?: modality!!).apply { - this.isExpect = isExpect - } - } - } - - // Returns a list of type parameters, and a substitutor that should be used for all other types - private fun createNewTypeParametersAndSubstitutor( - member: FirTypeParameterRefsOwner, - substitutor: ConeSubstitutor, - forceTypeParametersRecreation: Boolean = true - ): Pair, ConeSubstitutor> { - if (member.typeParameters.isEmpty()) return Pair(member.typeParameters, substitutor) - val newTypeParameters = member.typeParameters.map { typeParameter -> - if (typeParameter !is FirTypeParameter) return@map null - FirTypeParameterBuilder().apply { - source = typeParameter.source - session = typeParameter.session - origin = FirDeclarationOrigin.FakeOverride - name = typeParameter.name - symbol = FirTypeParameterSymbol() - variance = typeParameter.variance - isReified = typeParameter.isReified - annotations += typeParameter.annotations - } - } - - val substitutionMapForNewParameters = member.typeParameters.zip(newTypeParameters).mapNotNull { (original, new) -> - if (new != null) - Pair(original.symbol, ConeTypeParameterTypeImpl(new.symbol.toLookupTag(), isNullable = false)) - else null - }.toMap() - - val additionalSubstitutor = substitutorByMap(substitutionMapForNewParameters) - - var wereChangesInTypeParameters = forceTypeParametersRecreation - for ((newTypeParameter, oldTypeParameter) in newTypeParameters.zip(member.typeParameters)) { - if (newTypeParameter == null) continue - val original = oldTypeParameter as FirTypeParameter - for (boundTypeRef in original.bounds) { - val typeForBound = boundTypeRef.coneType - val substitutedBound = substitutor.substituteOrNull(typeForBound) - if (substitutedBound != null) { - wereChangesInTypeParameters = true - } - newTypeParameter.bounds += - buildResolvedTypeRef { - source = boundTypeRef.source - type = additionalSubstitutor.substituteOrSelf(substitutedBound ?: typeForBound) - } - } - } - - if (!wereChangesInTypeParameters) return Pair(member.typeParameters, substitutor) - return Pair( - newTypeParameters.mapIndexed { index, builder -> builder?.build() ?: member.typeParameters[index] }, - ChainedSubstitutor(substitutor, additionalSubstitutor) - ) - } + return FirFakeOverrideGenerator.createFakeOverrideAccessor(session, member, original, newReturnType, newParameterTypes) } override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDelegatedMemberScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDelegatedMemberScope.kt index 1623e7f909a..1fd0b4cb952 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDelegatedMemberScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirDelegatedMemberScope.kt @@ -38,7 +38,7 @@ class FirDelegatedMemberScope( val newSymbol = FirNamedFunctionSymbol( functionSymbol.callableId, ) - FirClassSubstitutionScope.createCopyForFirFunction( + FirFakeOverrideGenerator.createCopyForFirFunction( newSymbol, original, session, @@ -64,7 +64,7 @@ class FirDelegatedMemberScope( return@processor } val delegatedSymbol = delegatedPropertyCache.getOrPut(propertySymbol) { - FirClassSubstitutionScope.createCopyForFirProperty( + FirFakeOverrideGenerator.createCopyForFirProperty( FirPropertySymbol( propertySymbol.callableId, overriddenSymbol = propertySymbol diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirFakeOverrideGenerator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirFakeOverrideGenerator.kt new file mode 100644 index 00000000000..bf6bf7e2ed0 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirFakeOverrideGenerator.kt @@ -0,0 +1,420 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.scopes.impl + +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibility +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.builder.* +import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl +import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty +import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty +import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor +import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor +import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap +import org.jetbrains.kotlin.fir.symbols.CallableId +import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef +import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl +import org.jetbrains.kotlin.name.ClassId + +object FirFakeOverrideGenerator { + fun createFakeOverrideFunction( + session: FirSession, + baseFunction: FirSimpleFunction, + baseSymbol: FirNamedFunctionSymbol, + newReceiverType: ConeKotlinType? = null, + newReturnType: ConeKotlinType? = null, + newParameterTypes: List? = null, + newTypeParameters: List? = null, + derivedClassId: ClassId? = null, + isExpect: Boolean = baseFunction.isExpect + ): FirNamedFunctionSymbol { + val symbol = FirNamedFunctionSymbol( + CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseFunction.name), + isFakeOverride = true, overriddenSymbol = baseSymbol + ) + createFakeOverrideFunction( + symbol, session, baseFunction, newReceiverType, newReturnType, newParameterTypes, newTypeParameters, isExpect + ) + return symbol + } + + private fun createFakeOverrideFunction( + fakeOverrideSymbol: FirFunctionSymbol, + session: FirSession, + baseFunction: FirSimpleFunction, + newReceiverType: ConeKotlinType?, + newReturnType: ConeKotlinType?, + newParameterTypes: List?, + newTypeParameters: List?, + isExpect: Boolean = baseFunction.isExpect, + ): FirSimpleFunction { + // TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl + // As second alternative, we can invent some light-weight kind of FirRegularClass + return createCopyForFirFunction( + fakeOverrideSymbol, + baseFunction, + session, + FirDeclarationOrigin.FakeOverride, + isExpect, + newParameterTypes, + newTypeParameters, + newReceiverType, + newReturnType + ) + } + + fun createCopyForFirFunction( + newSymbol: FirFunctionSymbol, + baseFunction: FirSimpleFunction, + session: FirSession, + origin: FirDeclarationOrigin, + isExpect: Boolean = baseFunction.isExpect, + newParameterTypes: List? = null, + newTypeParameters: List? = null, + newReceiverType: ConeKotlinType? = null, + newReturnType: ConeKotlinType? = null, + newModality: Modality? = null, + newVisibility: Visibility? = null, + ): FirSimpleFunction { + return buildSimpleFunction { + source = baseFunction.source + this.session = session + this.origin = origin + name = baseFunction.name + status = baseFunction.status.updatedStatus(isExpect, newModality, newVisibility) + symbol = newSymbol + resolvePhase = baseFunction.resolvePhase + + typeParameters += configureAnnotationsTypeParametersAndSignature( + session, baseFunction, newParameterTypes, newTypeParameters, newReceiverType, newReturnType + ).filterIsInstance() + } + } + + fun createFakeOverrideConstructor( + fakeOverrideSymbol: FirConstructorSymbol, + session: FirSession, + baseConstructor: FirConstructor, + newReturnType: ConeKotlinType?, + newParameterTypes: List?, + newTypeParameters: List?, + isExpect: Boolean + ): FirConstructor { + // TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl + // As second alternative, we can invent some light-weight kind of FirRegularClass + return buildConstructor { + source = baseConstructor.source + this.session = session + origin = FirDeclarationOrigin.FakeOverride + receiverTypeRef = baseConstructor.receiverTypeRef?.withReplacedConeType(null) + status = baseConstructor.status.updatedStatus(isExpect) + symbol = fakeOverrideSymbol + resolvePhase = baseConstructor.resolvePhase + + typeParameters += configureAnnotationsTypeParametersAndSignature( + session, baseConstructor, newParameterTypes, newTypeParameters, newReceiverType = null, newReturnType + ) + } + } + + private fun FirFunctionBuilder.configureAnnotationsTypeParametersAndSignature( + session: FirSession, + baseFunction: FirFunction<*>, + newParameterTypes: List?, + newTypeParameters: List?, + newReceiverType: ConeKotlinType?, + newReturnType: ConeKotlinType? + ): List { + return when { + baseFunction.typeParameters.isEmpty() -> { + configureAnnotationsAndSignature(session, baseFunction, newParameterTypes, newReceiverType, newReturnType) + emptyList() + } + newTypeParameters == null -> { + val (copiedTypeParameters, substitutor) = createNewTypeParametersAndSubstitutor( + baseFunction, ConeSubstitutor.Empty + ) + val copiedParameterTypes = baseFunction.valueParameters.map { + substitutor.substituteOrNull(it.returnTypeRef.coneType) + } + val (copiedReceiverType, copiedReturnType) = substituteReceiverAndReturnType( + baseFunction as FirCallableMemberDeclaration<*>, newReceiverType, newReturnType, substitutor + ) + configureAnnotationsAndSignature(session, baseFunction, copiedParameterTypes, copiedReceiverType, copiedReturnType) + copiedTypeParameters + } + else -> { + configureAnnotationsAndSignature(session, baseFunction, newParameterTypes, newReceiverType, newReturnType) + newTypeParameters + } + } + } + + private fun FirFunctionBuilder.configureAnnotationsAndSignature( + session: FirSession, + baseFunction: FirFunction<*>, + newParameterTypes: List?, + newReceiverType: ConeKotlinType?, + newReturnType: ConeKotlinType? + ) { + annotations += baseFunction.annotations + returnTypeRef = replaceReturnTypeIfResolved(baseFunction, newReturnType) + + if (this is FirSimpleFunctionBuilder) { + receiverTypeRef = baseFunction.receiverTypeRef?.withReplacedConeType(newReceiverType) + } + valueParameters += baseFunction.valueParameters.zip( + newParameterTypes ?: List(baseFunction.valueParameters.size) { null } + ) { valueParameter, newType -> + buildValueParameterCopy(valueParameter) { + origin = FirDeclarationOrigin.FakeOverride + returnTypeRef = valueParameter.returnTypeRef.withReplacedConeType(newType) + symbol = FirVariableSymbol(valueParameter.symbol.callableId) + } + } + } + + private fun replaceReturnTypeIfResolved( + base: FirCallableDeclaration<*>, + newReturnType: ConeKotlinType? + ): FirTypeRef = if (base.returnTypeRef is FirResolvedTypeRef) + base.returnTypeRef.withReplacedConeType(newReturnType) + else + base.returnTypeRef + + fun createFakeOverrideProperty( + session: FirSession, + baseProperty: FirProperty, + baseSymbol: FirPropertySymbol, + newReceiverType: ConeKotlinType? = null, + newReturnType: ConeKotlinType? = null, + newTypeParameters: List? = null, + derivedClassId: ClassId? = null, + isExpect: Boolean = baseProperty.isExpect + ): FirPropertySymbol { + val symbol = FirPropertySymbol( + CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseProperty.name), + isFakeOverride = true, overriddenSymbol = baseSymbol + ) + createCopyForFirProperty( + symbol, baseProperty, session, isExpect, + newTypeParameters, newReceiverType, newReturnType + ) + return symbol + } + + fun createCopyForFirProperty( + newSymbol: FirPropertySymbol, + baseProperty: FirProperty, + session: FirSession, + isExpect: Boolean = baseProperty.isExpect, + newTypeParameters: List? = null, + newReceiverType: ConeKotlinType? = null, + newReturnType: ConeKotlinType? = null, + newModality: Modality? = null, + newVisibility: Visibility? = null, + ): FirProperty { + return buildProperty { + source = baseProperty.source + this.session = session + origin = FirDeclarationOrigin.FakeOverride + name = baseProperty.name + isVar = baseProperty.isVar + this.symbol = newSymbol + isLocal = false + status = baseProperty.status.updatedStatus(isExpect, newModality, newVisibility) + + resolvePhase = baseProperty.resolvePhase + typeParameters += configureAnnotationsTypeParametersAndSignature( + baseProperty, + newTypeParameters, + newReceiverType, + newReturnType + ) + } + } + + private fun FirPropertyBuilder.configureAnnotationsTypeParametersAndSignature( + baseProperty: FirProperty, + newTypeParameters: List?, + newReceiverType: ConeKotlinType?, + newReturnType: ConeKotlinType? + ): List { + return when { + baseProperty.typeParameters.isEmpty() -> { + configureAnnotationsAndSignature(baseProperty, newReceiverType, newReturnType) + emptyList() + } + newTypeParameters == null -> { + val (copiedTypeParameters, substitutor) = createNewTypeParametersAndSubstitutor( + baseProperty, ConeSubstitutor.Empty + ) + val (copiedReceiverType, copiedReturnType) = substituteReceiverAndReturnType( + baseProperty, newReceiverType, newReturnType, substitutor + ) + configureAnnotationsAndSignature(baseProperty, copiedReceiverType, copiedReturnType) + copiedTypeParameters.filterIsInstance() + } + else -> { + configureAnnotationsAndSignature(baseProperty, newReceiverType, newReturnType) + newTypeParameters + } + } + } + + private fun substituteReceiverAndReturnType( + baseCallable: FirCallableMemberDeclaration<*>, + newReceiverType: ConeKotlinType?, + newReturnType: ConeKotlinType?, + substitutor: ConeSubstitutor + ): Pair { + val copiedReceiverType = newReceiverType?.let { + substitutor.substituteOrNull(it) + } ?: baseCallable.receiverTypeRef?.let { + substitutor.substituteOrNull(it.coneType) + } + val copiedReturnType = newReturnType?.let { + substitutor.substituteOrNull(it) + } ?: baseCallable.returnTypeRef.let { + substitutor.substituteOrNull(it.coneType) + } + return copiedReceiverType to copiedReturnType + } + + private fun FirPropertyBuilder.configureAnnotationsAndSignature( + baseProperty: FirProperty, + newReceiverType: ConeKotlinType?, + newReturnType: ConeKotlinType? + ) { + annotations += baseProperty.annotations + returnTypeRef = replaceReturnTypeIfResolved(baseProperty, newReturnType) + receiverTypeRef = baseProperty.receiverTypeRef?.withReplacedConeType(newReceiverType) + } + + fun createFakeOverrideField( + session: FirSession, + baseField: FirField, + baseSymbol: FirFieldSymbol, + newReturnType: ConeKotlinType?, + derivedClassId: ClassId? + ): FirFieldSymbol { + val symbol = FirFieldSymbol( + CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseField.name) + ) + buildField { + source = baseField.source + this.session = session + origin = FirDeclarationOrigin.FakeOverride + resolvePhase = baseField.resolvePhase + returnTypeRef = baseField.returnTypeRef.withReplacedConeType(newReturnType) + name = baseField.name + this.symbol = symbol + isVar = baseField.isVar + status = baseField.status + resolvePhase = baseField.resolvePhase + annotations += baseField.annotations + } + return symbol + } + + fun createFakeOverrideAccessor( + session: FirSession, + baseProperty: FirSyntheticProperty, + baseSymbol: FirAccessorSymbol, + newReturnType: ConeKotlinType?, + newParameterTypes: List? + ): FirAccessorSymbol { + val functionSymbol = FirNamedFunctionSymbol(baseSymbol.accessorId) + val function = createFakeOverrideFunction( + functionSymbol, + session, + baseProperty.getter.delegate, + newReceiverType = null, + newReturnType, + newParameterTypes, + newTypeParameters = null + ) + return buildSyntheticProperty { + this.session = session + name = baseProperty.name + symbol = FirAccessorSymbol(baseSymbol.callableId, baseSymbol.accessorId) + delegateGetter = function + }.symbol + } + + private fun FirDeclarationStatus.updatedStatus( + isExpect: Boolean, + newModality: Modality? = null, + newVisibility: Visibility? = null, + ): FirDeclarationStatus { + return if (this.isExpect == isExpect && newModality == null && newVisibility == null) { + this + } else { + require(this is FirDeclarationStatusImpl) { "Unexpected class ${this::class}" } + this.resolved(newVisibility ?: visibility, newModality ?: modality!!).apply { + this.isExpect = isExpect + } + } + } + + // Returns a list of type parameters, and a substitutor that should be used for all other types + fun createNewTypeParametersAndSubstitutor( + member: FirTypeParameterRefsOwner, + substitutor: ConeSubstitutor, + forceTypeParametersRecreation: Boolean = true + ): Pair, ConeSubstitutor> { + if (member.typeParameters.isEmpty()) return Pair(member.typeParameters, substitutor) + val newTypeParameters = member.typeParameters.map { typeParameter -> + if (typeParameter !is FirTypeParameter) return@map null + FirTypeParameterBuilder().apply { + source = typeParameter.source + session = typeParameter.session + origin = FirDeclarationOrigin.FakeOverride + name = typeParameter.name + symbol = FirTypeParameterSymbol() + variance = typeParameter.variance + isReified = typeParameter.isReified + annotations += typeParameter.annotations + } + } + + val substitutionMapForNewParameters = member.typeParameters.zip(newTypeParameters).mapNotNull { (original, new) -> + if (new != null) + Pair(original.symbol, ConeTypeParameterTypeImpl(new.symbol.toLookupTag(), isNullable = false)) + else null + }.toMap() + + val additionalSubstitutor = substitutorByMap(substitutionMapForNewParameters) + + var wereChangesInTypeParameters = forceTypeParametersRecreation + for ((newTypeParameter, oldTypeParameter) in newTypeParameters.zip(member.typeParameters)) { + if (newTypeParameter == null) continue + val original = oldTypeParameter as FirTypeParameter + for (boundTypeRef in original.bounds) { + val typeForBound = boundTypeRef.coneType + val substitutedBound = substitutor.substituteOrNull(typeForBound) + if (substitutedBound != null) { + wereChangesInTypeParameters = true + } + newTypeParameter.bounds += + buildResolvedTypeRef { + source = boundTypeRef.source + type = additionalSubstitutor.substituteOrSelf(substitutedBound ?: typeForBound) + } + } + } + + if (!wereChangesInTypeParameters) return Pair(member.typeParameters, substitutor) + return Pair( + newTypeParameters.mapIndexed { index, builder -> builder?.build() ?: member.typeParameters[index] }, + ChainedSubstitutor(substitutor, additionalSubstitutor) + ) + } +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt index b004feb5175..c71abeac6fc 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt @@ -269,7 +269,7 @@ class FirTypeIntersectionScope private constructor( isIntersectionOverride = true ) val mostSpecificFunction = mostSpecific.fir - FirClassSubstitutionScope.createCopyForFirFunction( + FirFakeOverrideGenerator.createCopyForFirFunction( newSymbol, mostSpecificFunction, session, FirDeclarationOrigin.IntersectionOverride, mostSpecificFunction.isExpect, @@ -286,7 +286,7 @@ class FirTypeIntersectionScope private constructor( ): FirPropertySymbol { val newSymbol = FirPropertySymbol(mostSpecific.callableId, mostSpecific.isFakeOverride, mostSpecific, isIntersectionOverride = true) val mostSpecificProperty = mostSpecific.fir - FirClassSubstitutionScope.createCopyForFirProperty( + FirFakeOverrideGenerator.createCopyForFirProperty( newSymbol, mostSpecificProperty, mostSpecificProperty.session, newModality = newModality, newVisibility = newVisibility,