[FIR2IR] Approximate types for lambdas before passing to serialization

This commit is contained in:
simon.ogorodnik
2020-05-20 20:21:00 +03:00
parent b92194229c
commit dbc564e74e
4 changed files with 56 additions and 5 deletions
@@ -21,9 +21,15 @@ import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.builder.*
import org.jetbrains.kotlin.fir.inferenceContext
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.serialization.FirElementSerializer
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFunction
@@ -32,6 +38,9 @@ import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable
import org.jetbrains.kotlin.types.AbstractTypeApproximator
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.Method
@@ -52,16 +61,37 @@ class FirJvmClassCodegen(
else -> null
}
private val approximator = object : AbstractTypeApproximator(session.inferenceContext) {
override fun createErrorType(message: String): SimpleTypeMarker {
return ConeKotlinErrorType(message)
}
}
private fun FirTypeRef.approximated(
toSuper: Boolean,
conf: TypeApproximatorConfiguration = TypeApproximatorConfiguration.PublicDeclaration
): FirTypeRef {
val approximatedType = if (toSuper)
approximator.approximateToSuperType(this.coneTypeUnsafe(), conf)
else
approximator.approximateToSubType(this.coneTypeUnsafe(), conf)
return withReplacedConeType(approximatedType as? ConeKotlinType)
}
private fun FirFunction<*>.copyToFreeAnonymousFunction(): FirAnonymousFunction {
val function = this
return buildAnonymousFunction {
session = function.session
origin = FirDeclarationOrigin.Source
symbol = FirAnonymousFunctionSymbol()
returnTypeRef = function.returnTypeRef
receiverTypeRef = function.receiverTypeRef
returnTypeRef = function.returnTypeRef.approximated(toSuper = true)
receiverTypeRef = function.receiverTypeRef?.approximated(toSuper = false)
isLambda = (function as? FirAnonymousFunction)?.isLambda == true
valueParameters.addAll(function.valueParameters)
valueParameters.addAll(function.valueParameters.map {
buildValueParameterCopy(it) {
returnTypeRef = it.returnTypeRef.approximated(toSuper = false)
}
})
typeParameters.addAll(function.typeParameters.filterIsInstance<FirTypeParameter>())
}
}
@@ -72,3 +72,24 @@ inline fun buildValueParameter(init: FirValueParameterBuilder.() -> Unit): FirVa
}
return FirValueParameterBuilder().apply(init).build()
}
@OptIn(ExperimentalContracts::class)
inline fun buildValueParameterCopy(original: FirValueParameter, init: FirValueParameterBuilder.() -> Unit): FirValueParameter {
contract {
callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
}
val copyBuilder = FirValueParameterBuilder()
copyBuilder.source = original.source
copyBuilder.session = original.session
copyBuilder.resolvePhase = original.resolvePhase
copyBuilder.origin = original.origin
copyBuilder.returnTypeRef = original.returnTypeRef
copyBuilder.name = original.name
copyBuilder.symbol = original.symbol
copyBuilder.annotations.addAll(original.annotations)
copyBuilder.defaultValue = original.defaultValue
copyBuilder.isCrossinline = original.isCrossinline
copyBuilder.isNoinline = original.isNoinline
copyBuilder.isVararg = original.isVararg
return copyBuilder.apply(init).build()
}
@@ -245,6 +245,7 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
builder(valueParameter, type = "FirValueParameterImpl") {
openBuilder()
withCopy()
}
builder(valueParameter, type = "FirDefaultSetterValueParameter") {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
fun <R> foo(f: () -> R): R = f()