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).
This commit is contained in:
pyos
2020-09-15 18:35:05 +02:00
committed by Mikhail Glukhikh
parent aa58ed9234
commit 6e143a2656
3 changed files with 32 additions and 17 deletions
@@ -44,61 +44,79 @@ class FirMetadataSerializer(
} }
} }
private fun FirTypeRef.approximated(toSuper: Boolean): FirTypeRef { private fun FirTypeRef.approximated(toSuper: Boolean, typeParameterSet: MutableCollection<FirTypeParameter>): FirTypeRef {
val approximatedType = if (toSuper) val approximatedType = if (toSuper)
approximator.approximateToSuperType(coneType, TypeApproximatorConfiguration.PublicDeclaration) approximator.approximateToSuperType(coneType, TypeApproximatorConfiguration.PublicDeclaration)
else else
approximator.approximateToSubType(coneType, TypeApproximatorConfiguration.PublicDeclaration) 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<FirTypeParameter>) {
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 { private fun FirFunction<*>.copyToFreeAnonymousFunction(): FirAnonymousFunction {
val function = this val function = this
return buildAnonymousFunction { return buildAnonymousFunction {
val typeParameterSet = function.typeParameters.filterIsInstanceTo(mutableSetOf<FirTypeParameter>())
session = function.session session = function.session
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
symbol = FirAnonymousFunctionSymbol() symbol = FirAnonymousFunctionSymbol()
returnTypeRef = function.returnTypeRef.approximated(toSuper = true) returnTypeRef = function.returnTypeRef.approximated(toSuper = true, typeParameterSet)
receiverTypeRef = function.receiverTypeRef?.approximated(toSuper = false) receiverTypeRef = function.receiverTypeRef?.approximated(toSuper = false, typeParameterSet)
isLambda = (function as? FirAnonymousFunction)?.isLambda == true isLambda = (function as? FirAnonymousFunction)?.isLambda == true
valueParameters.addAll(function.valueParameters.map { valueParameters.addAll(function.valueParameters.map {
buildValueParameterCopy(it) { buildValueParameterCopy(it) {
returnTypeRef = it.returnTypeRef.approximated(toSuper = false) returnTypeRef = it.returnTypeRef.approximated(toSuper = false, typeParameterSet)
} }
}) })
// TODO need containers' type parameters too typeParameters += typeParameterSet
function.typeParameters.filterIsInstanceTo(typeParameters)
} }
} }
private fun FirPropertyAccessor.copyToFreeAccessor(): FirPropertyAccessor { private fun FirPropertyAccessor.copyToFreeAccessor(): FirPropertyAccessor {
val accessor = this val accessor = this
return buildPropertyAccessor { return buildPropertyAccessor {
val typeParameterSet = accessor.typeParameters.toMutableSet()
session = accessor.session session = accessor.session
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
returnTypeRef = accessor.returnTypeRef.approximated(toSuper = true) returnTypeRef = accessor.returnTypeRef.approximated(toSuper = true, typeParameterSet)
symbol = FirPropertyAccessorSymbol() symbol = FirPropertyAccessorSymbol()
isGetter = accessor.isGetter isGetter = accessor.isGetter
status = accessor.status status = accessor.status
accessor.valueParameters.mapTo(valueParameters) { accessor.valueParameters.mapTo(valueParameters) {
buildValueParameterCopy(it) { buildValueParameterCopy(it) {
returnTypeRef = it.returnTypeRef.approximated(toSuper = false) returnTypeRef = it.returnTypeRef.approximated(toSuper = false, typeParameterSet)
} }
} }
annotations += accessor.annotations annotations += accessor.annotations
// TODO need containers' type parameters too typeParameters += typeParameterSet
typeParameters += accessor.typeParameters
} }
} }
private fun FirProperty.copyToFreeProperty(): FirProperty { private fun FirProperty.copyToFreeProperty(): FirProperty {
val property = this val property = this
return buildProperty { return buildProperty {
val typeParameterSet = property.typeParameters.toMutableSet()
session = property.session session = property.session
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
symbol = FirPropertySymbol(property.symbol.callableId) symbol = FirPropertySymbol(property.symbol.callableId)
returnTypeRef = property.returnTypeRef.approximated(toSuper = true) returnTypeRef = property.returnTypeRef.approximated(toSuper = true, typeParameterSet)
receiverTypeRef = property.receiverTypeRef?.approximated(toSuper = false) receiverTypeRef = property.receiverTypeRef?.approximated(toSuper = false, typeParameterSet)
name = property.name name = property.name
initializer = property.initializer initializer = property.initializer
delegate = property.delegate delegate = property.delegate
@@ -111,8 +129,7 @@ class FirMetadataSerializer(
isLocal = property.isLocal isLocal = property.isLocal
status = property.status status = property.status
annotations += property.annotations annotations += property.annotations
// TODO need containers' type parameters too typeParameters += typeParameterSet
typeParameters += property.typeParameters
}.apply { }.apply {
delegateFieldSymbol?.fir = this delegateFieldSymbol?.fir = this
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JS_IR_ES6 // IGNORE_BACKEND: JS_IR_ES6
// TODO: muted automatically, investigate should it be ran for JS or not // TODO: muted automatically, investigate should it be ran for JS or not
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// WITH_REFLECT // WITH_REFLECT