[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.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirFunction import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter 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.serialization.FirElementSerializer
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol 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.IrClass
import org.jetbrains.kotlin.ir.declarations.IrField import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFunction 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.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable 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.Type
import org.jetbrains.org.objectweb.asm.commons.Method import org.jetbrains.org.objectweb.asm.commons.Method
@@ -52,16 +61,37 @@ class FirJvmClassCodegen(
else -> null 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 { private fun FirFunction<*>.copyToFreeAnonymousFunction(): FirAnonymousFunction {
val function = this val function = this
return buildAnonymousFunction { return buildAnonymousFunction {
session = function.session session = function.session
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
symbol = FirAnonymousFunctionSymbol() symbol = FirAnonymousFunctionSymbol()
returnTypeRef = function.returnTypeRef returnTypeRef = function.returnTypeRef.approximated(toSuper = true)
receiverTypeRef = function.receiverTypeRef receiverTypeRef = function.receiverTypeRef?.approximated(toSuper = false)
isLambda = (function as? FirAnonymousFunction)?.isLambda == true 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>()) typeParameters.addAll(function.typeParameters.filterIsInstance<FirTypeParameter>())
} }
} }
@@ -72,3 +72,24 @@ inline fun buildValueParameter(init: FirValueParameterBuilder.() -> Unit): FirVa
} }
return FirValueParameterBuilder().apply(init).build() 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") { builder(valueParameter, type = "FirValueParameterImpl") {
openBuilder() openBuilder()
withCopy()
} }
builder(valueParameter, type = "FirDefaultSetterValueParameter") { builder(valueParameter, type = "FirDefaultSetterValueParameter") {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST // !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
fun <R> foo(f: () -> R): R = f() fun <R> foo(f: () -> R): R = f()