From 6e143a26562e708a31a53a1d865c2d5bb31455b8 Mon Sep 17 00:00:00 2001 From: pyos Date: Tue, 15 Sep 2020 18:35:05 +0200 Subject: [PATCH] JVM_IR: collect free type parameters when serializing FIR metadata The "free" in "createFreeFakeLambdaDescriptor" and such refers to the fact that there are no references to type parameters from outside the current declaration. This is necessary because at the point where the metadata is written, the type parameters may not even be in scope (e.g. local delegated properties are serialized at class level, but may refer to function-scope type parameters). --- .../fir/backend/jvm/FirMetadataSerializer.kt | 47 +++++++++++++------ .../box/functions/functionNtoStringGeneric.kt | 1 - .../localDelegated/variableOfGenericType.kt | 1 - 3 files changed, 32 insertions(+), 17 deletions(-) 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