From 0054c22ef24bdaa4c3526fd0b0c054120b77a00f Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Thu, 2 Apr 2020 20:05:35 +0300 Subject: [PATCH] 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 leaked outside. --- .../compiler/backend/ir/GeneratorHelpers.kt | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt index 2323a144ab4..e2b87a02890 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions import org.jetbrains.kotlin.resolve.descriptorUtil.classId 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.makeNotNullable import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound @@ -494,16 +495,20 @@ interface IrBuilderExtension { expression: IrExpression, nullableSerializerClass: IrClassSymbol ): IrExpression { - return if (type.isMarkedNullable) + return if (type.isMarkedNullable) { + val nullableConstructor = + compilerContext.symbolTable.referenceConstructor(nullableSerializerClass.descriptor.constructors.toList().first()) + val resultType = type.makeNotNullable() irInvoke( - null, compilerContext.symbolTable.referenceConstructor(nullableSerializerClass.descriptor.constructors.toList().first()), - typeArguments = listOf(type.makeNotNullable().toIrType()), + null, nullableConstructor, + typeArguments = listOf(resultType.toIrType()), valueArguments = listOf(expression), - // Return type should not be different from declared class, otherwise, we will call wrong method on runtime. - returnTypeHint = null + // Return type should be correctly substituted + returnTypeHint = nullableConstructor.descriptor.returnType.replace(listOf(resultType.asTypeProjection())).toIrType() ) - else + } else { expression + } } @@ -657,8 +662,9 @@ interface IrBuilderExtension { } else { compilerContext.symbolTable.referenceConstructor(serializerClass.unsubstitutedPrimaryConstructor!!) } - // Return type should not be different from declared class, otherwise, we will call wrong method on runtime. - return irInvoke(null, ctor, typeArguments = typeArgs, valueArguments = args, returnTypeHint = null) + // Return type should be correctly substituted + val substitutedReturnType = ctor.descriptor.returnType.replace(typeArgs.map { it.toKotlinType().asTypeProjection() }).toIrType() + return irInvoke(null, ctor, typeArguments = typeArgs, valueArguments = args, returnTypeHint = substitutedReturnType) } }