Mark KClass for interop classes unimplemented explicitly

Also fix https://github.com/JetBrains/kotlin-native/issues/1973#issuecomment-417634981
This commit is contained in:
Svyatoslav Scherbina
2018-08-31 18:42:21 +03:00
committed by SvyatoslavScherbina
parent 7c37f3134f
commit 840c2f1b9f
5 changed files with 53 additions and 14 deletions
@@ -409,6 +409,8 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
val getObjectTypeInfo = internalFunction("getObjectTypeInfo")
val kClassImpl = internalClass("KClassImpl")
val kClassImplConstructor by lazy { kClassImpl.constructors.single() }
val kClassUnsupportedImpl = internalClass("KClassUnsupportedImpl")
val kClassUnsupportedImplConstructor by lazy { kClassUnsupportedImpl.constructors.single() }
val kTypeImpl = internalClass("KTypeImpl")
val kTypeImplForGenerics = internalClass("KTypeImplForGenerics")
@@ -2257,7 +2257,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
val typeArgument = callee.getTypeArgument(0)!!
val typeArgumentClass = typeArgument.getClass()
if (typeArgumentClass == null) {
// E.g. for `T::class` in a body of an inline function itself.
// Should not happen anymore, but it is safer to handle this case.
functionGenerationContext.unreachable()
kNullInt8Ptr
} else {
@@ -9,11 +9,14 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlock
import org.jetbrains.kotlin.backend.konan.InteropFqNames
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
import org.jetbrains.kotlin.backend.konan.getInlinedClass
import org.jetbrains.kotlin.backend.konan.irasdescriptors.typeWithStarProjections
import org.jetbrains.kotlin.backend.konan.isObjCClass
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.ir.IrStatement
@@ -28,8 +31,8 @@ import org.jetbrains.kotlin.ir.expressions.IrLocalDelegatedPropertyReference
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.toKotlinType
@@ -37,6 +40,8 @@ import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.TypeProjectionImpl
@@ -325,22 +330,43 @@ internal fun IrBuilderWithScope.irKType(context: KonanBackendContext, type: IrTy
val kTypeImplSymbol = context.ir.symbols.kTypeImpl
val kTypeImplForGenericsSymbol = context.ir.symbols.kTypeImplForGenerics
val kClassImplConstructorSymbol = context.ir.symbols.kClassImplConstructor
val kTypeImplConstructorSymbol = kTypeImplSymbol.constructors.single()
val kTypeImplForGenericsConstructorSymbol = kTypeImplForGenericsSymbol.constructors.single()
val getClassTypeInfoSymbol = context.ir.symbols.getClassTypeInfo
val classifierOrNull = type.classifierOrNull
return if (type.classifierOrNull !is IrClassSymbol) {
return if (classifierOrNull !is IrClassSymbol) {
// IrTypeParameterSymbol
irCall(kTypeImplForGenericsConstructorSymbol)
} else {
val returnKClass = irCall(kClassImplConstructorSymbol).apply {
putValueArgument(0, irCall(getClassTypeInfoSymbol, listOf(type)))
}
val returnKClass = irKClass(context, classifierOrNull)
irCall(kTypeImplConstructorSymbol).apply {
putValueArgument(0, returnKClass)
putValueArgument(1, irBoolean(type.isMarkedNullable()))
}
}
}
internal fun IrBuilderWithScope.irKClass(context: KonanBackendContext, symbol: IrClassifierSymbol): IrExpression {
val symbols = context.ir.symbols
return when {
symbol !is IrClassSymbol -> // E.g. for `T::class` in a body of an inline function itself.
irCall(symbols.ThrowNullPointerException.owner)
symbol.descriptor.isObjCClass() ->
irKClassUnsupported(context, "KClass for Objective-C classes is not supported yet")
symbol.descriptor.getAllSuperClassifiers().any {
it is ClassDescriptor && it.fqNameUnsafe == InteropFqNames.nativePointed
} -> irKClassUnsupported(context, "KClass for interop types is not supported yet")
else -> irCall(symbols.kClassImplConstructor.owner).apply {
putValueArgument(0, irCall(symbols.getClassTypeInfo, listOf(symbol.typeWithStarProjections)))
}
}
}
private fun IrBuilderWithScope.irKClassUnsupported(context: KonanBackendContext, message: String) =
irCall(context.ir.symbols.kClassUnsupportedImplConstructor.owner).apply {
putValueArgument(0, irString(message))
}
@@ -36,11 +36,7 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
val builder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol,
expression.startOffset, expression.endOffset)
val typeArgument = expression.symbol.typeWithStarProjections
return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply {
putValueArgument(0, builder.irCall(symbols.getClassTypeInfo, listOf(typeArgument)))
}
return builder.irKClass(context, expression.symbol)
}
override fun visitGetClass(expression: IrGetClass): IrExpression {
@@ -42,6 +42,21 @@ internal class KClassImpl<T : Any>(private val typeInfo: NativePtr) : KClass<T>
}
}
@PublishedApi
internal class KClassUnsupportedImpl(private val message: String) : KClass<Any> {
override val simpleName: String? get() = error(message)
override val qualifiedName: String? get() = error(message)
override fun isInstance(value: Any?): Boolean = error(message)
override fun equals(other: Any?): Boolean = error(message)
override fun hashCode(): Int = error(message)
override fun toString(): String = "unreflected class ($message)"
}
@ExportForCompiler
@SymbolName("Kotlin_Any_getTypeInfo")
internal external fun getObjectTypeInfo(obj: Any): NativePtr