From 29c03b258ae1123fa0e0054ab188322993bbaf0f Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Tue, 14 Aug 2018 16:58:33 +0300 Subject: [PATCH] Implemented KType, KCallable.returnType --- .../jetbrains/kotlin/backend/konan/ir/Ir.kt | 2 + .../konan/lower/CallableReferenceLowering.kt | 15 ++--- .../backend/konan/lower/DelegationLowering.kt | 32 +++++++++- .../kotlin/native/internal/KClassImpl.kt | 4 ++ .../kotlin/native/internal/KFunctionImpl.kt | 4 +- .../kotlin/native/internal/KPropertyImpl.kt | 29 ++++----- .../kotlin/native/internal/KTypeImpl.kt | 43 +++++++++++++ .../main/kotlin/kotlin/reflect/KCallable.kt | 12 ++-- .../src/main/kotlin/kotlin/reflect/KType.kt | 62 +++++++++++++++++++ 9 files changed, 168 insertions(+), 35 deletions(-) create mode 100644 runtime/src/main/kotlin/kotlin/native/internal/KTypeImpl.kt create mode 100644 runtime/src/main/kotlin/kotlin/reflect/KType.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt index 68d7e023a7c..15b669b506b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -353,6 +353,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 kTypeImpl = internalClass("KTypeImpl") + val kTypeImplForGenerics = internalClass("KTypeImplForGenerics") val listOfInternal = internalFunction("listOfInternal") diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt index 26a6f2b8408..454e5da6d2b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/CallableReferenceLowering.kt @@ -43,9 +43,7 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl -import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol -import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol +import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.types.* @@ -169,18 +167,19 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass private val kFunctionImplSymbol = context.ir.symbols.kFunctionImpl + private val kFunctionImplConstructorSymbol = kFunctionImplSymbol.constructors.single() + fun build(): BuiltFunctionReference { val startOffset = functionReference.startOffset val endOffset = functionReference.endOffset - val returnType = irFunction.returnType - val superTypes = mutableListOf(kFunctionImplSymbol.typeWith(returnType)) + val superTypes = mutableListOf(kFunctionImplSymbol.typeWith(irFunction.returnType)) val numberOfParameters = unboundFunctionParameters.size val functionIrClass = context.ir.symbols.kFunctions[numberOfParameters].owner val functionParameterTypes = unboundFunctionParameters.map { it.type } - val functionClassTypeParameters = functionParameterTypes + returnType + val functionClassTypeParameters = functionParameterTypes + irFunction.returnType superTypes += functionIrClass.symbol.typeWith(functionClassTypeParameters) var suspendFunctionIrClass: IrClass? = null @@ -256,8 +255,6 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass private fun createConstructorBuilder() = object : SymbolWithIrBuilder() { - private val kFunctionImplConstructorSymbol = kFunctionImplSymbol.constructors.single() - override fun buildSymbol() = IrConstructorSymbolImpl( ClassConstructorDescriptorImpl.create( /* containingDeclaration = */ functionReferenceClassDescriptor, @@ -278,7 +275,6 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass override fun buildIr(): IrConstructor { - val symbols = this@CallableReferenceLowering.context.ir.symbols val irBuiltIns = context.irBuiltIns argumentToPropertiesMap = boundFunctionParameters.associate { @@ -318,6 +314,7 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass val needReceiver = boundFunctionParameters.singleOrNull()?.descriptor is ReceiverParameterDescriptor val receiver = if (needReceiver) irGet(valueParameters.single()) else irNull() putValueArgument(3, receiver) + putValueArgument(4, irKType(this@CallableReferenceLowering.context, irFunction.returnType)) } +IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol, irBuiltIns.unitType) // Save all arguments to fields. diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt index bff22594f70..08d0a371303 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt @@ -36,7 +36,10 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression 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.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 import org.jetbrains.kotlin.ir.types.typeWith @@ -271,10 +274,11 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi isMutable = setterCallableReference != null) val initializer = irCall(symbol.owner, constructorTypeArguments).apply { putValueArgument(0, irString(propertyDescriptor.name.asString())) + putValueArgument(1, irKType(this@PropertyDelegationLowering.context, returnType)) if (getterCallableReference != null) - putValueArgument(1, getterCallableReference) + putValueArgument(2, getterCallableReference) if (setterCallableReference != null) - putValueArgument(2, setterCallableReference) + putValueArgument(3, setterCallableReference) } +initializer } @@ -291,6 +295,7 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi isMutable = false) val initializer = irCall(symbol.owner, constructorTypeArguments).apply { putValueArgument(0, irString(propertyDescriptor.name.asString())) + putValueArgument(1, irKType(this@PropertyDelegationLowering.context, propertyType)) } return initializer } @@ -323,3 +328,26 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi } } +internal fun IrBuilderWithScope.irKType(context: KonanBackendContext, type: IrType): IrExpression { + 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 + + return if (type.classifierOrNull !is IrClassSymbol) { + // IrTypeParameterSymbol + irCall(kTypeImplForGenericsConstructorSymbol) + } else { + val returnKClass = irCall(kClassImplConstructorSymbol).apply { + putValueArgument(0, irCall(getClassTypeInfoSymbol, listOf(type))) + } + irCall(kTypeImplConstructorSymbol).apply { + putValueArgument(0, returnKClass) + putValueArgument(1, irBoolean(type.isMarkedNullable())) + } + } +} diff --git a/runtime/src/main/kotlin/kotlin/native/internal/KClassImpl.kt b/runtime/src/main/kotlin/kotlin/native/internal/KClassImpl.kt index b5f4a0888e4..3c365f014c4 100644 --- a/runtime/src/main/kotlin/kotlin/native/internal/KClassImpl.kt +++ b/runtime/src/main/kotlin/kotlin/native/internal/KClassImpl.kt @@ -47,6 +47,10 @@ internal class KClassImpl(private val typeInfo: NativePtr) : KClass other is KClassImpl<*> && this.typeInfo == other.typeInfo override fun hashCode(): Int = typeInfo.hashCode() + + override fun toString(): String { + return "class " + (qualifiedName ?: simpleName ?: "") + } } @ExportForCompiler diff --git a/runtime/src/main/kotlin/kotlin/native/internal/KFunctionImpl.kt b/runtime/src/main/kotlin/kotlin/native/internal/KFunctionImpl.kt index 06f98593de2..35fa5f730e1 100644 --- a/runtime/src/main/kotlin/kotlin/native/internal/KFunctionImpl.kt +++ b/runtime/src/main/kotlin/kotlin/native/internal/KFunctionImpl.kt @@ -17,9 +17,11 @@ package kotlin.native.internal import kotlin.reflect.KFunction +import kotlin.reflect.KType @FixmeReflection -open class KFunctionImpl(override val name: String, val fqName: String, val bound: Boolean, val receiver: Any?): KFunction { +open class KFunctionImpl(override val name: String, val fqName: String, val bound: Boolean, val receiver: Any?, + override val returnType: KType): KFunction { override fun equals(other: Any?): Boolean { if (other !is KFunctionImpl<*>) return false return fqName == other.fqName && bound == other.bound && receiver == other.receiver diff --git a/runtime/src/main/kotlin/kotlin/native/internal/KPropertyImpl.kt b/runtime/src/main/kotlin/kotlin/native/internal/KPropertyImpl.kt index a5153d28592..dac5bb2f661 100644 --- a/runtime/src/main/kotlin/kotlin/native/internal/KPropertyImpl.kt +++ b/runtime/src/main/kotlin/kotlin/native/internal/KPropertyImpl.kt @@ -16,16 +16,11 @@ package kotlin.native.internal -import kotlin.reflect.KProperty0 -import kotlin.reflect.KProperty1 -import kotlin.reflect.KProperty2 -import kotlin.reflect.KMutableProperty0 -import kotlin.reflect.KMutableProperty1 -import kotlin.reflect.KMutableProperty2 import kotlin.UnsupportedOperationException +import kotlin.reflect.* @FixmeReflection -open class KProperty0Impl(override val name: String, val getter: () -> R): KProperty0 { +open class KProperty0Impl(override val name: String, override val returnType: KType, val getter: () -> R): KProperty0 { override fun get(): R { return getter() } @@ -49,7 +44,7 @@ open class KProperty0Impl(override val name: String, val getter: () -> R) } @FixmeReflection -open class KProperty1Impl(override val name: String, val getter: (T) -> R): KProperty1 { +open class KProperty1Impl(override val name: String, override val returnType: KType, val getter: (T) -> R): KProperty1 { override fun get(p1: T): R { return getter(p1) } @@ -73,7 +68,7 @@ open class KProperty1Impl(override val name: String, val getter: (T) - } @FixmeReflection -open class KProperty2Impl(override val name: String, val getter: (T1, T2) -> R): KProperty2 { +open class KProperty2Impl(override val name: String, override val returnType: KType, val getter: (T1, T2) -> R): KProperty2 { override fun get(p1: T1, p2: T2): R { return getter(p1, p2) } @@ -97,8 +92,8 @@ open class KProperty2Impl(override val name: String, val getter: } @FixmeReflection -class KMutableProperty0Impl(name: String, getter: () -> R, val setter: (R) -> Unit) - : KProperty0Impl(name, getter), KMutableProperty0 { +class KMutableProperty0Impl(name: String, returnType: KType, getter: () -> R, val setter: (R) -> Unit) + : KProperty0Impl(name, returnType, getter), KMutableProperty0 { override fun set(value: R): Unit { setter(value) } @@ -119,8 +114,8 @@ class KMutableProperty0Impl(name: String, getter: () -> R, val setter: (R) -> } @FixmeReflection -class KMutableProperty1Impl(name: String, getter: (T) -> R, val setter: (T, R) -> Unit) - : KProperty1Impl(name, getter), KMutableProperty1 { +class KMutableProperty1Impl(name: String, returnType: KType, getter: (T) -> R, val setter: (T, R) -> Unit) + : KProperty1Impl(name, returnType, getter), KMutableProperty1 { override fun set(receiver: T, value: R): Unit { setter(receiver, value) } @@ -141,8 +136,8 @@ class KMutableProperty1Impl(name: String, getter: (T) -> R, val setter: (T } @FixmeReflection -class KMutableProperty2Impl(name: String, getter: (T1, T2) -> R, val setter: (T1, T2, R) -> Unit) - : KProperty2Impl(name, getter), KMutableProperty2 { +class KMutableProperty2Impl(name: String, returnType: KType, getter: (T1, T2) -> R, val setter: (T1, T2, R) -> Unit) + : KProperty2Impl(name, returnType, getter), KMutableProperty2 { override fun set(receiver1: T1, receiver2: T2, value: R): Unit { setter(receiver1, receiver2, value) } @@ -162,7 +157,7 @@ class KMutableProperty2Impl(name: String, getter: (T1, T2) -> R, val } } -open class KLocalDelegatedPropertyImpl(override val name: String): KProperty0 { +open class KLocalDelegatedPropertyImpl(override val name: String, override val returnType: KType): KProperty0 { override fun get(): R { throw UnsupportedOperationException("Not supported for local property reference.") } @@ -175,7 +170,7 @@ open class KLocalDelegatedPropertyImpl(override val name: String): KPrope } } -class KLocalDelegatedMutablePropertyImpl(name: String): KLocalDelegatedPropertyImpl(name), KMutableProperty0 { +class KLocalDelegatedMutablePropertyImpl(name: String, returnType: KType): KLocalDelegatedPropertyImpl(name, returnType), KMutableProperty0 { override fun set(value: R): Unit { throw UnsupportedOperationException("Not supported for local property reference.") } diff --git a/runtime/src/main/kotlin/kotlin/native/internal/KTypeImpl.kt b/runtime/src/main/kotlin/kotlin/native/internal/KTypeImpl.kt new file mode 100644 index 00000000000..c8ceebb137b --- /dev/null +++ b/runtime/src/main/kotlin/kotlin/native/internal/KTypeImpl.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.native.internal + +import kotlin.reflect.KClassifier +import kotlin.reflect.KType + +internal class KTypeImpl(override val classifier: KClassifier?, override val isMarkedNullable: Boolean) : KType { + override fun equals(other: Any?) = + other is KTypeImpl && classifier == other.classifier && isMarkedNullable == other.isMarkedNullable + + override fun hashCode(): Int { + return (classifier?.hashCode() ?: 0) * 31 + if (isMarkedNullable) 1 else 0 + } +} + +internal class KTypeImplForGenerics : KType { + override val classifier: KClassifier? + get() = error("Generic types are not yet supported in reflection") + + override val isMarkedNullable: Boolean + get() = error("Generic types are not yet supported in reflection") + + override fun equals(other: Any?) = + error("Generic types are not yet supported in reflection") + + override fun hashCode(): Int = + error("Generic types are not yet supported in reflection") +} \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/reflect/KCallable.kt b/runtime/src/main/kotlin/kotlin/reflect/KCallable.kt index 6fbab69ad53..276c28fcd6d 100644 --- a/runtime/src/main/kotlin/kotlin/reflect/KCallable.kt +++ b/runtime/src/main/kotlin/kotlin/reflect/KCallable.kt @@ -39,12 +39,12 @@ public interface KCallable : KAnnotatedElement { // * they come first in the list in that order. // */ // public val parameters: List -// -// /** -// * The type of values returned by this callable. -// */ -// public val returnType: KType -// + + /** + * The type of values returned by this callable. + */ + public val returnType: KType + // /** // * The list of type parameters of this callable. // */ diff --git a/runtime/src/main/kotlin/kotlin/reflect/KType.kt b/runtime/src/main/kotlin/kotlin/reflect/KType.kt new file mode 100644 index 00000000000..3c83d4e004b --- /dev/null +++ b/runtime/src/main/kotlin/kotlin/reflect/KType.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlin.reflect + +/** + * Represents a type. Type is usually either a class with optional type arguments, + * or a type parameter of some declaration, plus nullability. + */ +public interface KType { + /** + * The declaration of the classifier used in this type. + * For example, in the type `List` the classifier would be the [KClass] instance for [List]. + * + * Returns `null` if this type is not denotable in Kotlin, for example if it is an intersection type. + */ + @SinceKotlin("1.1") + public val classifier: KClassifier? + + /** + * Type arguments passed for the parameters of the classifier in this type. + * For example, in the type `Array` the only type argument is `out Number`. + * + * In case this type is based on an inner class, the returned list contains the type arguments provided for the innermost class first, + * then its outer class, and so on. + * For example, in the type `Outer.Inner` the returned list is `[C, D, A, B]`. + */ +// @SinceKotlin("1.1") +// public val arguments: List + + /** + * `true` if this type was marked nullable in the source code. + * + * For Kotlin types, it means that `null` value is allowed to be represented by this type. + * In practice it means that the type was declared with a question mark at the end. + * For non-Kotlin types, it means the type or the symbol which was declared with this type + * is annotated with a runtime-retained nullability annotation such as [javax.annotation.Nullable]. + * + * Note that even if [isMarkedNullable] is false, values of the type can still be `null`. + * This may happen if it is a type of the type parameter with a nullable upper bound: + * + * ``` + * fun foo(t: T) { + * // isMarkedNullable == false for t's type, but t can be null here when T = "Any?" + * } + * ``` + */ + public val isMarkedNullable: Boolean +} \ No newline at end of file