diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt index 2d38b0da95e..167813df43a 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt @@ -44,61 +44,79 @@ class FirMetadataSerializer( } } - private fun FirTypeRef.approximated(toSuper: Boolean): FirTypeRef { + private fun FirTypeRef.approximated(toSuper: Boolean, typeParameterSet: MutableCollection): FirTypeRef { val approximatedType = if (toSuper) approximator.approximateToSuperType(coneType, TypeApproximatorConfiguration.PublicDeclaration) else approximator.approximateToSubType(coneType, TypeApproximatorConfiguration.PublicDeclaration) - return withReplacedConeType(approximatedType as? ConeKotlinType) + return withReplacedConeType(approximatedType as? ConeKotlinType).apply { coneType.collectTypeParameters(typeParameterSet) } + } + + private fun ConeKotlinType.collectTypeParameters(c: MutableCollection) { + when (this) { + is ConeFlexibleType -> { + lowerBound.collectTypeParameters(c) + upperBound.collectTypeParameters(c) + } + is ConeClassLikeType -> + for (projection in type.typeArguments) { + if (projection is ConeKotlinTypeProjection) { + projection.type.collectTypeParameters(c) + } + } + is ConeTypeParameterType -> c.add(lookupTag.typeParameterSymbol.fir) + else -> Unit + } } private fun FirFunction<*>.copyToFreeAnonymousFunction(): FirAnonymousFunction { val function = this return buildAnonymousFunction { + val typeParameterSet = function.typeParameters.filterIsInstanceTo(mutableSetOf()) session = function.session origin = FirDeclarationOrigin.Source symbol = FirAnonymousFunctionSymbol() - returnTypeRef = function.returnTypeRef.approximated(toSuper = true) - receiverTypeRef = function.receiverTypeRef?.approximated(toSuper = false) + returnTypeRef = function.returnTypeRef.approximated(toSuper = true, typeParameterSet) + receiverTypeRef = function.receiverTypeRef?.approximated(toSuper = false, typeParameterSet) isLambda = (function as? FirAnonymousFunction)?.isLambda == true valueParameters.addAll(function.valueParameters.map { buildValueParameterCopy(it) { - returnTypeRef = it.returnTypeRef.approximated(toSuper = false) + returnTypeRef = it.returnTypeRef.approximated(toSuper = false, typeParameterSet) } }) - // TODO need containers' type parameters too - function.typeParameters.filterIsInstanceTo(typeParameters) + typeParameters += typeParameterSet } } private fun FirPropertyAccessor.copyToFreeAccessor(): FirPropertyAccessor { val accessor = this return buildPropertyAccessor { + val typeParameterSet = accessor.typeParameters.toMutableSet() session = accessor.session origin = FirDeclarationOrigin.Source - returnTypeRef = accessor.returnTypeRef.approximated(toSuper = true) + returnTypeRef = accessor.returnTypeRef.approximated(toSuper = true, typeParameterSet) symbol = FirPropertyAccessorSymbol() isGetter = accessor.isGetter status = accessor.status accessor.valueParameters.mapTo(valueParameters) { buildValueParameterCopy(it) { - returnTypeRef = it.returnTypeRef.approximated(toSuper = false) + returnTypeRef = it.returnTypeRef.approximated(toSuper = false, typeParameterSet) } } annotations += accessor.annotations - // TODO need containers' type parameters too - typeParameters += accessor.typeParameters + typeParameters += typeParameterSet } } private fun FirProperty.copyToFreeProperty(): FirProperty { val property = this return buildProperty { + val typeParameterSet = property.typeParameters.toMutableSet() session = property.session origin = FirDeclarationOrigin.Source symbol = FirPropertySymbol(property.symbol.callableId) - returnTypeRef = property.returnTypeRef.approximated(toSuper = true) - receiverTypeRef = property.receiverTypeRef?.approximated(toSuper = false) + returnTypeRef = property.returnTypeRef.approximated(toSuper = true, typeParameterSet) + receiverTypeRef = property.receiverTypeRef?.approximated(toSuper = false, typeParameterSet) name = property.name initializer = property.initializer delegate = property.delegate @@ -111,8 +129,7 @@ class FirMetadataSerializer( isLocal = property.isLocal status = property.status annotations += property.annotations - // TODO need containers' type parameters too - typeParameters += property.typeParameters + typeParameters += typeParameterSet }.apply { delegateFieldSymbol?.fir = this } diff --git a/compiler/testData/codegen/box/functions/functionNtoStringGeneric.kt b/compiler/testData/codegen/box/functions/functionNtoStringGeneric.kt index e0eb226047a..7e9313d7852 100644 --- a/compiler/testData/codegen/box/functions/functionNtoStringGeneric.kt +++ b/compiler/testData/codegen/box/functions/functionNtoStringGeneric.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR_ES6 // TODO: muted automatically, investigate should it be ran for JS or not diff --git a/compiler/testData/codegen/box/reflection/properties/localDelegated/variableOfGenericType.kt b/compiler/testData/codegen/box/reflection/properties/localDelegated/variableOfGenericType.kt index 7a66782157e..71e0440f6eb 100644 --- a/compiler/testData/codegen/box/reflection/properties/localDelegated/variableOfGenericType.kt +++ b/compiler/testData/codegen/box/reflection/properties/localDelegated/variableOfGenericType.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM // WITH_REFLECT