backend: support boxing when generics involved

This commit is contained in:
Svyatoslav Scherbina
2017-01-10 17:34:39 +07:00
committed by SvyatoslavScherbina
parent 83bdae5d02
commit 0e6d8c3a7c
2 changed files with 26 additions and 13 deletions
@@ -103,7 +103,7 @@ internal fun KonanBuiltIns.getKonanInternalClassOrNull(name: String): ClassDescr
* @return built-in class `konan.internal.$name` * @return built-in class `konan.internal.$name`
*/ */
internal fun KonanBuiltIns.getKonanInternalClass(name: String): ClassDescriptor = internal fun KonanBuiltIns.getKonanInternalClass(name: String): ClassDescriptor =
getKonanInternalClassOrNull(name)!! getKonanInternalClassOrNull(name) ?: TODO(name)
internal fun KonanBuiltIns.getKonanInternalFunctions(name: String): List<FunctionDescriptor> { internal fun KonanBuiltIns.getKonanInternalFunctions(name: String): List<FunctionDescriptor> {
return konanInternal.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).toList() return konanInternal.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).toList()
@@ -9,9 +9,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.unboundCallableReferenceTy
import org.jetbrains.kotlin.descriptors.ParameterDescriptor import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid 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 { 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 { override fun IrExpression.useAsArgument(parameter: ParameterDescriptor): IrExpression {
val thisRepresentation = getCustomRepresentation(this.type) 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) val expectedRepresentation = getCustomRepresentation(expectedType)
return when { return when {
thisRepresentation == expectedRepresentation -> this actualRepresentation == expectedRepresentation -> this
thisRepresentation == null && expectedRepresentation != null -> { actualRepresentation == null && expectedRepresentation != null -> {
// This may happen in the following cases: // This may happen in the following cases:
// 1. `this.type` is `Nothing`; // 1. `actualType` is `Nothing`;
// 2. `this` has the incompatible type. // 2. `actualType` is incompatible.
this.unbox(expectedRepresentation) 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")
} }
} }