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`
*/
internal fun KonanBuiltIns.getKonanInternalClass(name: String): ClassDescriptor =
getKonanInternalClassOrNull(name)!!
getKonanInternalClassOrNull(name) ?: TODO(name)
internal fun KonanBuiltIns.getKonanInternalFunctions(name: String): List<FunctionDescriptor> {
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.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")
}
}