From ef6c5364a66737c4caa03774a2a312781b607872 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Mon, 23 Jan 2017 11:22:13 +0700 Subject: [PATCH] backend: fix handling `T?` as type operand: Preserve erased type nullability in type operations lowering. Also make erasure more strict to detect unsupported cases. --- .../konan/lower/TypeOperatorLowering.kt | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt index f5f5b277748..cbf34eb8774 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt @@ -4,6 +4,7 @@ import org.jetbrains.kotlin.backend.common.FunctionLoweringPass import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.IrStatement @@ -18,6 +19,7 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.types.typeUtil.makeNotNullable +import org.jetbrains.kotlin.types.typeUtil.makeNullable /** * This lowering pass lowers some [IrTypeOperatorCall]s. @@ -43,15 +45,22 @@ private class TypeOperatorTransformer(val context: Context, val function: Functi return declaration } - private tailrec fun KotlinType.erasure(): KotlinType { + private fun KotlinType.erasure(): KotlinType { val descriptor = this.constructor.declarationDescriptor - return if (descriptor is TypeParameterDescriptor) { - val upperBound = descriptor.upperBounds.singleOrNull() ?: - TODO("$descriptor : ${descriptor.upperBounds}") + return when (descriptor) { + is ClassDescriptor -> this + is TypeParameterDescriptor -> { + val upperBound = descriptor.upperBounds.singleOrNull() ?: + TODO("$descriptor : ${descriptor.upperBounds}") - upperBound.erasure() - } else { - this + if (this.isMarkedNullable) { + // `T?` + upperBound.erasure().makeNullable() + } else { + upperBound.erasure() + } + } + else -> TODO(this.toString()) } }