Add KType.arguments and support 'typeOf' intrinsic
#KT-29917 Fixed #KT-28625 Fixed Also perform minor refactoring.
This commit is contained in:
committed by
SvyatoslavScherbina
parent
f704fd44af
commit
e0d6a4c70e
+1
@@ -41,6 +41,7 @@ class KonanReflectionTypes(module: ModuleDescriptor, internalPackage: FqName) {
|
||||
val kMutableProperty0: ClassDescriptor by ClassLookup(kotlinReflectScope)
|
||||
val kMutableProperty1: ClassDescriptor by ClassLookup(kotlinReflectScope)
|
||||
val kMutableProperty2: ClassDescriptor by ClassLookup(kotlinReflectScope)
|
||||
val kTypeProjection: ClassDescriptor by ClassLookup(kotlinReflectScope)
|
||||
|
||||
val kFunctionImpl: ClassDescriptor by ClassLookup(internalScope)
|
||||
val kProperty0Impl: ClassDescriptor by ClassLookup(internalScope)
|
||||
|
||||
+42
-3
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
@@ -30,8 +29,10 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
// This is what Context collects about IR.
|
||||
@@ -249,8 +250,11 @@ internal class KonanSymbols(context: Context, private val symbolTable: SymbolTab
|
||||
{ findArrayExtension(it.descriptor, "contentHashCode") }
|
||||
)
|
||||
|
||||
private val kotlinCollectionsPackageScope: MemberScope
|
||||
get() = builtInsPackage("kotlin", "collections")
|
||||
|
||||
private fun findArrayExtension(descriptor: ClassDescriptor, name: String): IrSimpleFunctionSymbol {
|
||||
val functionDescriptor = builtInsPackage("kotlin", "collections")
|
||||
val functionDescriptor = kotlinCollectionsPackageScope
|
||||
.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND)
|
||||
.singleOrNull {
|
||||
it.valueParameters.isEmpty()
|
||||
@@ -403,6 +407,41 @@ internal class KonanSymbols(context: Context, private val symbolTable: SymbolTab
|
||||
val kTypeImpl = internalClass("KTypeImpl")
|
||||
val kTypeImplForGenerics = internalClass("KTypeImplForGenerics")
|
||||
|
||||
val kTypeProjection = symbolTable.referenceClass(context.reflectionTypes.kTypeProjection)
|
||||
|
||||
private val kTypeProjectionCompanionDescriptor = context.reflectionTypes.kTypeProjection.companionObjectDescriptor!!
|
||||
|
||||
val kTypeProjectionCompanion = symbolTable.referenceClass(kTypeProjectionCompanionDescriptor)
|
||||
|
||||
val kTypeProjectionStar = symbolTable.referenceProperty(
|
||||
kTypeProjectionCompanionDescriptor.unsubstitutedMemberScope
|
||||
.getContributedVariables(Name.identifier("STAR"), NoLookupLocation.FROM_BACKEND).single()
|
||||
)
|
||||
|
||||
val kTypeProjectionFactories: Map<Variance, IrSimpleFunctionSymbol> = Variance.values().toList().associateWith {
|
||||
val factoryName = when (it) {
|
||||
Variance.INVARIANT -> "invariant"
|
||||
Variance.IN_VARIANCE -> "contravariant"
|
||||
Variance.OUT_VARIANCE -> "covariant"
|
||||
}
|
||||
|
||||
symbolTable.referenceSimpleFunction(
|
||||
kTypeProjectionCompanionDescriptor.unsubstitutedMemberScope
|
||||
.getContributedFunctions(Name.identifier(factoryName), NoLookupLocation.FROM_BACKEND).single()
|
||||
)
|
||||
}
|
||||
|
||||
val emptyList = symbolTable.referenceSimpleFunction(
|
||||
kotlinCollectionsPackageScope
|
||||
.getContributedFunctions(Name.identifier("emptyList"), NoLookupLocation.FROM_BACKEND)
|
||||
.single { it.valueParameters.isEmpty() }
|
||||
)
|
||||
|
||||
val listOf = symbolTable.referenceSimpleFunction(
|
||||
kotlinCollectionsPackageScope
|
||||
.getContributedFunctions(Name.identifier("listOf"), NoLookupLocation.FROM_BACKEND)
|
||||
.single { it.valueParameters.size == 1 && it.valueParameters[0].isVararg }
|
||||
)
|
||||
val listOfInternal = internalFunction("listOfInternal")
|
||||
|
||||
val threadLocal =
|
||||
|
||||
+3
-1
@@ -40,6 +40,8 @@ internal class CallableReferenceLowering(val context: Context): FileLoweringPass
|
||||
|
||||
private object DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL : IrDeclarationOriginImpl("FUNCTION_REFERENCE_IMPL")
|
||||
|
||||
private val kTypeGenerator = KTypeGenerator(context)
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
var generatedClasses = mutableListOf<IrClass>()
|
||||
irFile.transform(object: IrElementTransformerVoidWithContext() {
|
||||
@@ -266,7 +268,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, referencedFunction.returnType))
|
||||
putValueArgument(4, with(kTypeGenerator) { irKType(referencedFunction.returnType) })
|
||||
}
|
||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol, irBuiltIns.unitType)
|
||||
// Save all arguments to fields.
|
||||
|
||||
+4
-2
@@ -34,6 +34,8 @@ import org.jetbrains.kotlin.name.Name
|
||||
internal class PropertyDelegationLowering(val context: Context) : FileLoweringPass {
|
||||
private var tempIndex = 0
|
||||
|
||||
private val kTypeGenerator = KTypeGenerator(context)
|
||||
|
||||
private fun getKPropertyImplConstructor(receiverTypes: List<IrType>,
|
||||
returnType: IrType,
|
||||
isLocal: Boolean,
|
||||
@@ -253,7 +255,7 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
||||
isMutable = setterCallableReference != null)
|
||||
val initializer = irCall(symbol.owner, constructorTypeArguments).apply {
|
||||
putValueArgument(0, irString(propertyDescriptor.name.asString()))
|
||||
putValueArgument(1, irKType(this@PropertyDelegationLowering.context, returnType))
|
||||
putValueArgument(1, with(kTypeGenerator) { irKType(returnType) })
|
||||
if (getterCallableReference != null)
|
||||
putValueArgument(2, getterCallableReference)
|
||||
if (setterCallableReference != null)
|
||||
@@ -274,7 +276,7 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
||||
isMutable = false)
|
||||
val initializer = irCall(symbol.owner, constructorTypeArguments).apply {
|
||||
putValueArgument(0, irString(propertyDescriptor.name.asString()))
|
||||
putValueArgument(1, irKType(this@PropertyDelegationLowering.context, propertyType))
|
||||
putValueArgument(1, with(kTypeGenerator) { irKType(propertyType) })
|
||||
}
|
||||
return initializer
|
||||
}
|
||||
|
||||
+2
@@ -47,6 +47,8 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
||||
return expression
|
||||
if (Symbols.isLateinitIsInitializedPropertyGetter(callee.symbol))
|
||||
return expression
|
||||
if (callee.isTypeOfIntrinsic())
|
||||
return expression
|
||||
|
||||
val actualCallee = getFunctionDeclaration(callee.symbol)
|
||||
|
||||
|
||||
+28
-5
@@ -9,12 +9,16 @@ 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.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.error
|
||||
import org.jetbrains.kotlin.backend.konan.ir.typeWithoutArguments
|
||||
import org.jetbrains.kotlin.backend.konan.reportCompilationError
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.util.irCall
|
||||
import org.jetbrains.kotlin.ir.util.isTypeOfIntrinsic
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
/**
|
||||
@@ -26,23 +30,32 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
|
||||
|
||||
private val symbols get() = context.ir.symbols
|
||||
|
||||
private val kTypeGenerator = KTypeGenerator(
|
||||
context,
|
||||
eraseTypeParameters = true // Mimic JVM BE behaviour until proper type parameter impl is ready.
|
||||
)
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
||||
|
||||
override fun visitClassReference(expression: IrClassReference): IrExpression {
|
||||
expression.transformChildrenVoid()
|
||||
|
||||
val builder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol,
|
||||
expression.startOffset, expression.endOffset)
|
||||
val builder = createIrBuilder(expression)
|
||||
|
||||
return builder.irKClass(context, expression.symbol)
|
||||
val symbol = expression.symbol
|
||||
return if (symbol is IrClassSymbol) {
|
||||
builder.irKClass(context, symbol)
|
||||
} else {
|
||||
// E.g. for `T::class` in a body of an inline function itself.
|
||||
builder.irCall(context.ir.symbols.ThrowNullPointerException.owner)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitGetClass(expression: IrGetClass): IrExpression {
|
||||
expression.transformChildrenVoid()
|
||||
|
||||
val builder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol,
|
||||
expression.startOffset, expression.endOffset)
|
||||
val builder = createIrBuilder(expression)
|
||||
|
||||
val typeArgument = expression.argument.type
|
||||
|
||||
@@ -91,10 +104,20 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
|
||||
expression.startOffset, expression.endOffset,
|
||||
context.ir.symbols.immutableBlob.typeWithoutArguments,
|
||||
IrConstKind.String, builder.toString()))
|
||||
} else if (expression.symbol.owner.isTypeOfIntrinsic()) {
|
||||
val type = expression.getTypeArgument(0)
|
||||
?: error(irFile, expression, "missing type argument")
|
||||
return with (kTypeGenerator) { createIrBuilder(expression).irKType(type) }
|
||||
}
|
||||
|
||||
return expression
|
||||
}
|
||||
|
||||
private fun createIrBuilder(element: IrElement) = context.createIrBuilder(
|
||||
currentScope!!.scope.scopeOwnerSymbol,
|
||||
element.startOffset,
|
||||
element.endOffset
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
+79
-27
@@ -8,50 +8,102 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
import org.jetbrains.kotlin.backend.konan.InteropFqNames
|
||||
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
||||
import org.jetbrains.kotlin.backend.konan.ir.typeWithStarProjections
|
||||
import org.jetbrains.kotlin.backend.konan.ir.typeWithoutArguments
|
||||
import org.jetbrains.kotlin.backend.konan.isObjCClass
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
|
||||
import org.jetbrains.kotlin.ir.builders.irBoolean
|
||||
import org.jetbrains.kotlin.ir.builders.irCall
|
||||
import org.jetbrains.kotlin.ir.builders.irString
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.types.isMarkedNullable
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.irCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
|
||||
|
||||
internal fun IrBuilderWithScope.irKType(context: KonanBackendContext, type: IrType): IrExpression {
|
||||
val kTypeImplSymbol = context.ir.symbols.kTypeImpl
|
||||
val kTypeImplForGenericsSymbol = context.ir.symbols.kTypeImplForGenerics
|
||||
internal class KTypeGenerator(
|
||||
private val context: KonanBackendContext,
|
||||
private val eraseTypeParameters: Boolean = false
|
||||
) {
|
||||
private val symbols = context.ir.symbols
|
||||
|
||||
val kTypeImplConstructorSymbol = kTypeImplSymbol.constructors.single()
|
||||
val kTypeImplForGenericsConstructorSymbol = kTypeImplForGenericsSymbol.constructors.single()
|
||||
|
||||
val classifierOrNull = type.classifierOrNull
|
||||
|
||||
return if (classifierOrNull !is IrClassSymbol) {
|
||||
// IrTypeParameterSymbol
|
||||
irCall(kTypeImplForGenericsConstructorSymbol)
|
||||
fun IrBuilderWithScope.irKType(type: IrType): IrExpression = if (type !is IrSimpleType) {
|
||||
// Represent as non-denotable type:
|
||||
irKTypeImpl(
|
||||
kClassifier = irNull(),
|
||||
irTypeArguments = emptyList(),
|
||||
isMarkedNullable = false
|
||||
)
|
||||
} else {
|
||||
val returnKClass = irKClass(context, classifierOrNull)
|
||||
irCall(kTypeImplConstructorSymbol).apply {
|
||||
putValueArgument(0, returnKClass)
|
||||
putValueArgument(1, irBoolean(type.isMarkedNullable()))
|
||||
val classifier = type.classifier
|
||||
|
||||
if (classifier is IrClassSymbol) {
|
||||
irKTypeImpl(
|
||||
kClassifier = irKClass(classifier),
|
||||
irTypeArguments = type.arguments,
|
||||
isMarkedNullable = type.hasQuestionMark
|
||||
)
|
||||
} else {
|
||||
if (eraseTypeParameters) {
|
||||
irKType(context.irBuiltIns.anyNType)
|
||||
} else {
|
||||
irCall(symbols.kTypeImplForGenerics.constructors.single())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.irKTypeImpl(
|
||||
kClassifier: IrExpression,
|
||||
irTypeArguments: List<IrTypeArgument>,
|
||||
isMarkedNullable: Boolean
|
||||
): IrExpression = irCall(symbols.kTypeImpl.constructors.single()).apply {
|
||||
putValueArgument(0, kClassifier)
|
||||
putValueArgument(1, irKTypeProjectionsList(irTypeArguments))
|
||||
putValueArgument(2, irBoolean(isMarkedNullable))
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.irKClass(symbol: IrClassSymbol) = irKClass(this@KTypeGenerator.context, symbol)
|
||||
|
||||
private fun IrBuilderWithScope.irKTypeProjectionsList(
|
||||
irTypeArguments: List<IrTypeArgument>
|
||||
): IrMemberAccessExpression {
|
||||
val kTypeProjectionType = symbols.kTypeProjection.typeWithoutArguments
|
||||
|
||||
return if (irTypeArguments.isEmpty()) {
|
||||
irCall(symbols.emptyList, listOf(kTypeProjectionType))
|
||||
} else {
|
||||
irCall(symbols.listOf, listOf(kTypeProjectionType)).apply {
|
||||
putValueArgument(0, IrVarargImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
type = symbols.array.typeWith(kTypeProjectionType),
|
||||
varargElementType = kTypeProjectionType,
|
||||
elements = irTypeArguments.map { irKTypeProjection(it) }
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.irKTypeProjection(argument: IrTypeArgument): IrExpression {
|
||||
return when (argument) {
|
||||
is IrTypeProjection -> irCall(symbols.kTypeProjectionFactories.getValue(argument.variance)).apply {
|
||||
dispatchReceiver = irGetObject(symbols.kTypeProjectionCompanion)
|
||||
putValueArgument(0, irKType(argument.type))
|
||||
}
|
||||
|
||||
is IrStarProjection -> irCall(symbols.kTypeProjectionStar.owner.getter!!).apply {
|
||||
dispatchReceiver = irGetObject(symbols.kTypeProjectionCompanion)
|
||||
}
|
||||
|
||||
else -> error("Unexpected IrTypeArgument: $argument (${argument::class})")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun IrBuilderWithScope.irKClass(context: KonanBackendContext, symbol: IrClassifierSymbol): IrExpression {
|
||||
internal fun IrBuilderWithScope.irKClass(context: KonanBackendContext, symbol: IrClassSymbol): 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")
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.backend.konan.KonanCompilationException
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.ir.allParameters
|
||||
import org.jetbrains.kotlin.backend.konan.ir.containsNull
|
||||
import org.jetbrains.kotlin.builtins.KOTLIN_REFLECT_FQ_NAME
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
@@ -434,3 +435,8 @@ fun IrClass.defaultOrNullableType(hasQuestionMark: Boolean) =
|
||||
|
||||
fun IrFunction.isRestrictedSuspendFunction(languageVersionSettings: LanguageVersionSettings): Boolean =
|
||||
this.descriptor.extensionReceiverParameter?.type?.isRestrictsSuspensionReceiver(languageVersionSettings) == true
|
||||
|
||||
fun IrFunction.isTypeOfIntrinsic(): Boolean =
|
||||
this.name.asString() == "typeOf" &&
|
||||
this.valueParameters.isEmpty() &&
|
||||
(this.parent as? IrPackageFragment)?.fqName == KOTLIN_REFLECT_FQ_NAME
|
||||
|
||||
@@ -5,15 +5,21 @@
|
||||
|
||||
package kotlin.native.internal
|
||||
|
||||
import kotlin.reflect.KClassifier
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.*
|
||||
|
||||
internal class KTypeImpl(override val classifier: KClassifier?, override val isMarkedNullable: Boolean) : KType {
|
||||
internal class KTypeImpl(
|
||||
override val classifier: KClassifier?,
|
||||
override val arguments: List<KTypeProjection>,
|
||||
override val isMarkedNullable: Boolean
|
||||
) : KType {
|
||||
override fun equals(other: Any?) =
|
||||
other is KTypeImpl && classifier == other.classifier && isMarkedNullable == other.isMarkedNullable
|
||||
other is KTypeImpl &&
|
||||
this.classifier == other.classifier &&
|
||||
this.arguments == other.arguments &&
|
||||
this.isMarkedNullable == other.isMarkedNullable
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return (classifier?.hashCode() ?: 0) * 31 + if (isMarkedNullable) 1 else 0
|
||||
return (classifier?.hashCode() ?: 0) * 31 * 31 + this.arguments.hashCode() * 31 + if (isMarkedNullable) 1 else 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +27,8 @@ internal class KTypeImplForGenerics : KType {
|
||||
override val classifier: KClassifier?
|
||||
get() = error("Generic types are not yet supported in reflection")
|
||||
|
||||
override val arguments: List<KTypeProjection> get() = emptyList()
|
||||
|
||||
override val isMarkedNullable: Boolean
|
||||
get() = error("Generic types are not yet supported in reflection")
|
||||
|
||||
|
||||
@@ -19,6 +19,17 @@ public interface KType {
|
||||
@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<out Number>` 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<A, B>.Inner<C, D>` the returned list is `[C, D, A, B]`.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
public val arguments: List<KTypeProjection>
|
||||
|
||||
/**
|
||||
* `true` if this type was marked nullable in the source code.
|
||||
*
|
||||
@@ -37,4 +48,57 @@ public interface KType {
|
||||
* ```
|
||||
*/
|
||||
public val isMarkedNullable: Boolean
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a type projection. Type projection is usually the argument to another type in a type usage.
|
||||
* For example, in the type `Array<out Number>`, `out Number` is the covariant projection of the type represented by the class `Number`.
|
||||
*
|
||||
* Type projection is either the star projection, or an entity consisting of a specific type plus optional variance.
|
||||
*
|
||||
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/generics.html#type-projections)
|
||||
* for more information.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
public data class KTypeProjection constructor(
|
||||
/**
|
||||
* The use-site variance specified in the projection, or `null` if this is a star projection.
|
||||
*/
|
||||
public val variance: KVariance?,
|
||||
/**
|
||||
* The type specified in the projection, or `null` if this is a star projection.
|
||||
*/
|
||||
public val type: KType?
|
||||
) {
|
||||
public companion object {
|
||||
/**
|
||||
* Star projection, denoted by the `*` character.
|
||||
* For example, in the type `KClass<*>`, `*` is the star projection.
|
||||
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/generics.html#star-projections)
|
||||
* for more information.
|
||||
*/
|
||||
public val STAR: KTypeProjection = KTypeProjection(null, null)
|
||||
|
||||
/**
|
||||
* Creates an invariant projection of a given type. Invariant projection is just the type itself,
|
||||
* without any use-site variance modifiers applied to it.
|
||||
* For example, in the type `Set<String>`, `String` is an invariant projection of the type represented by the class `String`.
|
||||
*/
|
||||
public fun invariant(type: KType): KTypeProjection =
|
||||
KTypeProjection(KVariance.INVARIANT, type)
|
||||
|
||||
/**
|
||||
* Creates a contravariant projection of a given type, denoted by the `in` modifier applied to a type.
|
||||
* For example, in the type `MutableList<in Number>`, `in Number` is a contravariant projection of the type of class `Number`.
|
||||
*/
|
||||
public fun contravariant(type: KType): KTypeProjection =
|
||||
KTypeProjection(KVariance.IN, type)
|
||||
|
||||
/**
|
||||
* Creates a covariant projection of a given type, denoted by the `out` modifier applied to a type.
|
||||
* For example, in the type `Array<out Number>`, `out Number` is a covariant projection of the type of class `Number`.
|
||||
*/
|
||||
public fun covariant(type: KType): KTypeProjection =
|
||||
KTypeProjection(KVariance.OUT, type)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package kotlin.reflect
|
||||
|
||||
/**
|
||||
* Represents variance applied to a type parameter on the declaration site (*declaration-site variance*),
|
||||
* or to a type in a projection (*use-site variance*).
|
||||
*
|
||||
* See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/generics.html#variance)
|
||||
* for more information.
|
||||
*
|
||||
* @see [KTypeParameter.variance]
|
||||
* @see [KTypeProjection]
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
enum class KVariance {
|
||||
/**
|
||||
* The affected type parameter or type is *invariant*, which means it has no variance applied to it.
|
||||
*/
|
||||
INVARIANT,
|
||||
|
||||
/**
|
||||
* The affected type parameter or type is *contravariant*. Denoted by the `in` modifier in the source code.
|
||||
*/
|
||||
IN,
|
||||
|
||||
/**
|
||||
* The affected type parameter or type is *covariant*. Denoted by the `out` modifier in the source code.
|
||||
*/
|
||||
OUT,
|
||||
}
|
||||
Reference in New Issue
Block a user