From 0e6d8c3a7c8f16458e058df5f570194b80ac187e Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Tue, 10 Jan 2017 17:34:39 +0700 Subject: [PATCH] backend: support boxing when generics involved --- .../konan/descriptors/DescriptorUtils.kt | 2 +- .../kotlin/backend/konan/lower/Autoboxing.kt | 37 +++++++++++++------ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt index f0e09c14593..b6c5dd58f24 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt @@ -103,7 +103,7 @@ internal fun KonanBuiltIns.getKonanInternalClassOrNull(name: String): ClassDescr * @return built-in class `konan.internal.$name` */ internal fun KonanBuiltIns.getKonanInternalClass(name: String): ClassDescriptor = - getKonanInternalClassOrNull(name)!! + getKonanInternalClassOrNull(name) ?: TODO(name) internal fun KonanBuiltIns.getKonanInternalFunctions(name: String): List { return konanInternal.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).toList() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt index 79ed2578c40..51994a3c352 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/Autoboxing.kt @@ -9,9 +9,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.unboundCallableReferenceTy import org.jetbrains.kotlin.descriptors.ParameterDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrTypeOperator -import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall +import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid @@ -120,27 +118,42 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr } override fun IrExpression.useAs(type: KotlinType): IrExpression { - return this.adaptIfNecessary(type) + + val actualType = when (this) { + is IrCall -> this.descriptor.original.returnType ?: this.type + is IrGetField -> this.descriptor.original.type + else -> this.type + } + + return this.adaptIfNecessary(actualType, type) } - private fun IrExpression.adaptIfNecessary(expectedType: KotlinType): IrExpression { - val thisRepresentation = getCustomRepresentation(this.type) + override fun IrExpression.useAsArgument(parameter: ParameterDescriptor): IrExpression { + return this.useAsValue(parameter.original) + } + + override fun IrExpression.useForField(field: PropertyDescriptor): IrExpression { + return this.useForVariable(field.original) + } + + private fun IrExpression.adaptIfNecessary(actualType: KotlinType, expectedType: KotlinType): IrExpression { + val actualRepresentation = getCustomRepresentation(actualType) val expectedRepresentation = getCustomRepresentation(expectedType) return when { - thisRepresentation == expectedRepresentation -> this + actualRepresentation == expectedRepresentation -> this - thisRepresentation == null && expectedRepresentation != null -> { + actualRepresentation == null && expectedRepresentation != null -> { // This may happen in the following cases: - // 1. `this.type` is `Nothing`; - // 2. `this` has the incompatible type. + // 1. `actualType` is `Nothing`; + // 2. `actualType` is incompatible. this.unbox(expectedRepresentation) } - thisRepresentation != null && expectedRepresentation == null -> this.box(thisRepresentation) + actualRepresentation != null && expectedRepresentation == null -> this.box(actualRepresentation) - else -> throw IllegalArgumentException("this is ${this.type}, expected $expectedType") + else -> throw IllegalArgumentException("actual type is $actualType, expected $expectedType") } }