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:
+32
-15
@@ -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)
|
||||
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<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 {
|
||||
val function = this
|
||||
return buildAnonymousFunction {
|
||||
val typeParameterSet = function.typeParameters.filterIsInstanceTo(mutableSetOf<FirTypeParameter>())
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_REFLECT
|
||||
|
||||
|
||||
Reference in New Issue
Block a user