Use correct return type for serializers

from runtime library.
If used unsubstituted, they cause
e: java.lang.IllegalArgumentException: Unbound type parameters are forbidden
because type parameter T from e.g. PolymorphicSerializer<T> leaked outside.
This commit is contained in:
Leonid Startsev
2020-04-02 20:05:35 +03:00
parent 75c4607e57
commit 0054c22ef2
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions
import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
@@ -494,16 +495,20 @@ interface IrBuilderExtension {
expression: IrExpression, expression: IrExpression,
nullableSerializerClass: IrClassSymbol nullableSerializerClass: IrClassSymbol
): IrExpression { ): IrExpression {
return if (type.isMarkedNullable) return if (type.isMarkedNullable) {
val nullableConstructor =
compilerContext.symbolTable.referenceConstructor(nullableSerializerClass.descriptor.constructors.toList().first())
val resultType = type.makeNotNullable()
irInvoke( irInvoke(
null, compilerContext.symbolTable.referenceConstructor(nullableSerializerClass.descriptor.constructors.toList().first()), null, nullableConstructor,
typeArguments = listOf(type.makeNotNullable().toIrType()), typeArguments = listOf(resultType.toIrType()),
valueArguments = listOf(expression), valueArguments = listOf(expression),
// Return type should not be different from declared class, otherwise, we will call wrong <init> method on runtime. // Return type should be correctly substituted
returnTypeHint = null returnTypeHint = nullableConstructor.descriptor.returnType.replace(listOf(resultType.asTypeProjection())).toIrType()
) )
else } else {
expression expression
}
} }
@@ -657,8 +662,9 @@ interface IrBuilderExtension {
} else { } else {
compilerContext.symbolTable.referenceConstructor(serializerClass.unsubstitutedPrimaryConstructor!!) compilerContext.symbolTable.referenceConstructor(serializerClass.unsubstitutedPrimaryConstructor!!)
} }
// Return type should not be different from declared class, otherwise, we will call wrong <init> method on runtime. // Return type should be correctly substituted
return irInvoke(null, ctor, typeArguments = typeArgs, valueArguments = args, returnTypeHint = null) val substitutedReturnType = ctor.descriptor.returnType.replace(typeArgs.map { it.toKotlinType().asTypeProjection() }).toIrType()
return irInvoke(null, ctor, typeArguments = typeArgs, valueArguments = args, returnTypeHint = substitutedReturnType)
} }
} }