From b7d098af5622a8b11d4adbc340af36d8e5d0f6c7 Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Tue, 12 Mar 2019 19:22:18 +0300 Subject: [PATCH] [IR] Implement `captureFromArguments` for `IrType` --- .../kotlin/ir/types/IrTypeCheckerContext.kt | 8 ++-- .../kotlin/ir/types/IrTypeSystemContext.kt | 48 ++++++++++++++++++- .../kotlin/ir/types/impl/IrSimpleTypeImpl.kt | 5 ++ 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeCheckerContext.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeCheckerContext.kt index c8da5ac0442..125af07e276 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeCheckerContext.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeCheckerContext.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.ir.types import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.types.impl.makeTypeIntersection import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.types.AbstractTypeCheckerContext import org.jetbrains.kotlin.types.Variance @@ -23,11 +24,10 @@ class IrTypeCheckerContext(override val irBuiltIns: IrBuiltIns) : IrTypeSystemCo } } - override fun areEqualTypeConstructors(a: TypeConstructorMarker, b: TypeConstructorMarker) = a === b + override fun areEqualTypeConstructors(a: TypeConstructorMarker, b: TypeConstructorMarker) = super.isEqualTypeConstructors(a, b) - override fun intersectTypes(types: List): KotlinTypeMarker { - TODO("not implemented") - } + @Suppress("UNCHECKED_CAST") + override fun intersectTypes(types: List) = makeTypeIntersection(types as List) override val isErrorTypeEqualsToAnything = false override val KotlinTypeMarker.isAllowedTypeVariable: Boolean diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt index cafaf8e59ac..de0df8a701f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt @@ -13,6 +13,9 @@ import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl +import org.jetbrains.kotlin.ir.types.impl.makeTypeIntersection +import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection +import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.checker.convertVariance import org.jetbrains.kotlin.types.model.* @@ -116,8 +119,49 @@ interface IrTypeSystemContext : TypeSystemContext { return classSymbol.owner.run { modality == Modality.FINAL && kind != ClassKind.ENUM_CLASS && kind != ClassKind.ANNOTATION_CLASS } } - // TODO: is that correct? - override fun captureFromArguments(type: SimpleTypeMarker, status: CaptureStatus): SimpleTypeMarker? = type + /* + * fun foo(x: Array) {} + * fun bar(y: Array) { + * foo(y) + * } + * + * In this case Captured Type of `y` would be `Array` + * + * See https://jetbrains.github.io/kotlin-spec/#type-capturing + */ + override fun captureFromArguments(type: SimpleTypeMarker, status: CaptureStatus): SimpleTypeMarker? { + // TODO: is that correct? + require(type is IrSimpleType) + + val classifier = type.classifier as IrClassSymbol + val typeArguments = type.arguments + + if (!classifier.isBound) return null + + val typeParameters = classifier.owner.typeParameters + + require(typeArguments.size == typeParameters.size) + + if (typeArguments.all { it is IrTypeProjection && it.variance == Variance.INVARIANT }) return type + + val newArguments = mutableListOf() + for (index in typeArguments.indices) { + val argument = typeArguments[index] + val parameter = typeParameters[index] + + if (argument is IrTypeProjection && argument.variance == Variance.INVARIANT) { + newArguments += argument + continue + } + + val additionalBounds = + if (argument is IrTypeProjection && argument.variance == Variance.OUT_VARIANCE) listOf(argument.type) else emptyList() + + newArguments += makeTypeProjection(makeTypeIntersection(parameter.superTypes + additionalBounds), Variance.INVARIANT) + } + + return IrSimpleTypeImpl(type.classifier, type.hasQuestionMark, newArguments, type.annotations) + } override fun SimpleTypeMarker.asArgumentList() = this as IrSimpleType diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrSimpleTypeImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrSimpleTypeImpl.kt index 41adedd72ba..b3ccd8298e8 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrSimpleTypeImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrSimpleTypeImpl.kt @@ -97,3 +97,8 @@ fun makeTypeProjection(type: IrType, variance: Variance): IrTypeProjection = type is IrErrorType -> IrErrorTypeImpl(null, type.annotations, variance) else -> IrTypeProjectionImpl(type, variance) } + + +fun makeTypeIntersection(types: List) = + if (types.size == 1) types[1] + else TODO("Not implemented") \ No newline at end of file