From 1d61d752255263f1fe711a65346059ee2ea26615 Mon Sep 17 00:00:00 2001 From: Dmitry Savvinov Date: Wed, 10 Jul 2019 13:47:16 +0300 Subject: [PATCH] [Core API] Introduce KotlinType.refine The most interesting part happens in SimpleType.refine, other types either don't implement refinement at all (they return just 'this', mainly it's some special types, like ErrorType and such) or implement it trivially via recursion (those are "composite" types) SimpleType.refine captures so-called refinement factory, which is essentially an injected callback which tells how to reconstruct the type with new (refined) memberScope. We have to inject callback because we express quite different types with SimpleTypeImpl, and some of them need different refinement logic. Another possible implementation approach (more invasive one) would be to extract those types in separate subtypes of KotlinType and implement 'refine' via overrides. The most meaningful callbacks are injected from 'AbstractClassDescriptor.defaultType' and from 'KotlinTypeFactory'. --- .../jetbrains/kotlin/types/DeferredType.java | 33 +++++- .../common/descriptors/WrappedDescriptors.kt | 4 +- .../kotlin/load/java/lazy/types/RawType.kt | 26 +++- .../java/typeEnhancement/typeEnhancement.kt | 4 + .../impl/AbstractClassDescriptor.java | 17 ++- .../impl/AbstractTypeAliasDescriptor.kt | 13 +- .../inference/CapturedTypeConstructor.kt | 6 + .../org/jetbrains/kotlin/types/ErrorType.kt | 8 ++ .../types/IntersectionTypeConstructor.kt | 5 +- .../org/jetbrains/kotlin/types/KotlinType.kt | 33 ++++++ .../kotlin/types/KotlinTypeFactory.kt | 112 ++++++++++++++---- .../jetbrains/kotlin/types/SpecialTypes.kt | 34 +++++- .../kotlin/types/StarProjectionImpl.kt | 14 ++- .../org/jetbrains/kotlin/types/StubType.kt | 7 +- .../kotlin/types/TypeProjection.java | 6 + .../kotlin/types/TypeProjectionImpl.java | 9 ++ .../org/jetbrains/kotlin/types/TypeUtils.java | 24 +++- .../kotlin/types/TypeWithEnhancement.kt | 21 ++++ .../kotlin/types/checker/NewCapturedType.kt | 11 ++ .../jetbrains/kotlin/types/dynamicTypes.kt | 6 +- .../jetbrains/kotlin/types/flexibleTypes.kt | 10 ++ 21 files changed, 364 insertions(+), 39 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/DeferredType.java b/compiler/frontend/src/org/jetbrains/kotlin/types/DeferredType.java index 5c7d348d7f2..0c06987bcfe 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/DeferredType.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/DeferredType.java @@ -22,6 +22,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.storage.NotNullLazyValue; import org.jetbrains.kotlin.storage.StorageManager; +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner; +import org.jetbrains.kotlin.types.refinement.TypeRefinement; import org.jetbrains.kotlin.util.Box; import org.jetbrains.kotlin.util.ReenteringLazyValueComputationException; @@ -43,7 +45,7 @@ public class DeferredType extends WrappedType { trace.record(DEFERRED_TYPE, new Box<>(deferredType)); return deferredType; } - + @NotNull /*package private*/ static DeferredType createRecursionIntolerant( @NotNull StorageManager storageManager, @@ -60,9 +62,38 @@ public class DeferredType extends WrappedType { private final NotNullLazyValue lazyValue; private DeferredType(@NotNull NotNullLazyValue lazyValue) { + super(); this.lazyValue = lazyValue; } + @NotNull + @Override + public KotlinType refine(@NotNull KotlinTypeRefiner kotlinTypeRefiner) { + return new DeferredType(new NotNullLazyValue() { + @NotNull + @Override + public String renderDebugInformation() { + return lazyValue.renderDebugInformation(); + } + + @Override + public boolean isComputed() { + return lazyValue.isComputed(); + } + + @Override + public boolean isComputing() { + return lazyValue.isComputing(); + } + + @Override + @TypeRefinement + public KotlinType invoke() { + return kotlinTypeRefiner.refineType(lazyValue.invoke()); + } + }); + } + public boolean isComputing() { return lazyValue.isComputing(); } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt index 6a5baaf0f32..b68847ab0b1 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt @@ -580,7 +580,7 @@ open class WrappedClassDescriptor( private val _defaultType: SimpleType by lazy { - TypeUtils.makeUnsubstitutedType(this, unsubstitutedMemberScope) + TypeUtils.makeUnsubstitutedType(this, unsubstitutedMemberScope) { unsubstitutedMemberScope } } override fun getDefaultType(): SimpleType = _defaultType @@ -691,7 +691,7 @@ open class WrappedEnumEntryDescriptor( private val _defaultType: SimpleType by lazy { - TypeUtils.makeUnsubstitutedType(this, unsubstitutedMemberScope) + TypeUtils.makeUnsubstitutedType(this, unsubstitutedMemberScope) { unsubstitutedMemberScope } } override fun getDefaultType(): SimpleType = _defaultType diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/types/RawType.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/types/RawType.kt index 160a6ec0c87..6905e443dc5 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/types/RawType.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/types/RawType.kt @@ -24,9 +24,12 @@ import org.jetbrains.kotlin.load.java.components.TypeUsage import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRendererOptions import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.checker.KotlinTypeChecker +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner +import org.jetbrains.kotlin.types.refinement.TypeRefinement import org.jetbrains.kotlin.types.typeUtil.builtIns class RawTypeImpl(lowerBound: SimpleType, upperBound: SimpleType) : FlexibleType(lowerBound, upperBound), RawType { @@ -80,6 +83,12 @@ class RawTypeImpl(lowerBound: SimpleType, upperBound: SimpleType) : FlexibleType if (newLower == newUpper) return newLower return renderer.renderFlexibleType(newLower, newUpper, builtIns) } + + @TypeRefinement + @UseExperimental(TypeRefinement::class) + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): FlexibleType { + return RawTypeImpl(kotlinTypeRefiner.refineType(lowerBound) as SimpleType, kotlinTypeRefiner.refineType(upperBound) as SimpleType) + } } internal object RawSubstitution : TypeSubstitution() { @@ -124,13 +133,20 @@ internal object RawSubstitution : TypeSubstitution() { if (type.isError) return ErrorUtils.createErrorType("Raw error type: ${type.constructor}") to false + val memberScope = declaration.getMemberScope(RawSubstitution) return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope( type.annotations, type.constructor, type.constructor.parameters.map { parameter -> computeProjection(parameter, attr) }, - type.isMarkedNullable, declaration.getMemberScope(RawSubstitution) - ) to true + type.isMarkedNullable, memberScope + ) factory@{ kotlinTypeRefiner -> + val classId = (declaration as? ClassDescriptor)?.classId ?: return@factory memberScope + + kotlinTypeRefiner + .findClassAcrossModuleDependencies(classId) + ?.getRefinedMemberScopeIfPossible(RawSubstitution, moduleDescriptor) ?: memberScope + } to true } fun computeProjection( @@ -150,13 +166,13 @@ internal object RawSubstitution : TypeSubstitution() { ) JavaTypeFlexibility.FLEXIBLE_UPPER_BOUND, JavaTypeFlexibility.INFLEXIBLE -> { if (!parameter.variance.allowsOutPosition) - // in T -> Comparable + // in T -> Comparable TypeProjectionImpl(Variance.INVARIANT, parameter.builtIns.nothingType) else if (erasedUpperBound.constructor.parameters.isNotEmpty()) - // T : Enum -> out Enum<*> + // T : Enum -> out Enum<*> TypeProjectionImpl(Variance.OUT_VARIANCE, erasedUpperBound) else - // T : String -> * + // T : String -> * makeStarProjection(parameter, attr) } } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/typeEnhancement/typeEnhancement.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/typeEnhancement/typeEnhancement.kt index 1ec73eecced..2aba640720e 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/typeEnhancement/typeEnhancement.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/typeEnhancement/typeEnhancement.kt @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.kotlin.types.refinement.TypeRefinement import org.jetbrains.kotlin.types.typeUtil.createProjection import org.jetbrains.kotlin.types.typeUtil.isTypeParameter @@ -253,4 +254,7 @@ internal class NotNullTypeParameter(override val delegate: SimpleType) : NotNull override fun replaceAnnotations(newAnnotations: Annotations) = NotNullTypeParameter(delegate.replaceAnnotations(newAnnotations)) override fun makeNullableAsSpecified(newNullability: Boolean) = if (newNullability) delegate.makeNullableAsSpecified(true) else this + + @TypeRefinement + override fun replaceDelegate(delegate: SimpleType) = NotNullTypeParameter(delegate) } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java index a1812029037..57bbc594436 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.descriptors.impl; import kotlin.jvm.functions.Function0; +import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.name.Name; @@ -43,7 +44,21 @@ public abstract class AbstractClassDescriptor extends ModuleAwareClassDescriptor this.defaultType = storageManager.createLazyValue(new Function0() { @Override public SimpleType invoke() { - return TypeUtils.makeUnsubstitutedType(AbstractClassDescriptor.this, getUnsubstitutedMemberScope()); + return TypeUtils.makeUnsubstitutedType( + AbstractClassDescriptor.this, getUnsubstitutedMemberScope(), + new Function1() { + @Override + public MemberScope invoke(KotlinTypeRefiner kotlinTypeRefiner) { + ClassDescriptor descriptor = kotlinTypeRefiner.refineDescriptor(AbstractClassDescriptor.this); + if (descriptor == null) return getUnsubstitutedMemberScope(kotlinTypeRefiner); + + if (descriptor instanceof ModuleAwareClassDescriptor) { + return ((ModuleAwareClassDescriptor) descriptor).getUnsubstitutedMemberScope(kotlinTypeRefiner); + } + return descriptor.getUnsubstitutedMemberScope(); + } + } + ); } }); this.unsubstitutedInnerClassesScope = storageManager.createLazyValue(new Function0() { diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeAliasDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeAliasDescriptor.kt index 74473890d7f..e27714124ba 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeAliasDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeAliasDescriptor.kt @@ -21,9 +21,13 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner +import org.jetbrains.kotlin.types.refinement.TypeRefinement +import org.jetbrains.kotlin.utils.addToStdlib.safeAs abstract class AbstractTypeAliasDescriptor( containingDeclaration: DeclarationDescriptor, @@ -89,8 +93,15 @@ abstract class AbstractTypeAliasDescriptor( protected abstract fun getTypeConstructorTypeParameters(): List + @UseExperimental(TypeRefinement::class) protected fun computeDefaultType(): SimpleType = - TypeUtils.makeUnsubstitutedType(this, classDescriptor?.unsubstitutedMemberScope ?: MemberScope.Empty) + TypeUtils.makeUnsubstitutedType(this, classDescriptor?.unsubstitutedMemberScope ?: MemberScope.Empty) { kotlinTypeRefiner -> + classDescriptor + ?.let { kotlinTypeRefiner.refineDescriptor(it) } + ?.safeAs() + ?.unsubstitutedMemberScope + ?: MemberScope.Empty + } private val typeConstructor = object : TypeConstructor { override fun getDeclarationDescriptor(): TypeAliasDescriptor = diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt index 04a4f973e91..404a58d0b38 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt @@ -24,8 +24,10 @@ import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.Variance.IN_VARIANCE import org.jetbrains.kotlin.types.Variance.OUT_VARIANCE +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.checker.NewCapturedTypeConstructor import org.jetbrains.kotlin.types.model.CapturedTypeMarker +import org.jetbrains.kotlin.types.refinement.TypeRefinement import org.jetbrains.kotlin.types.typeUtil.builtIns interface CapturedTypeConstructor : TypeConstructor { @@ -102,6 +104,10 @@ class CapturedType( override fun replaceAnnotations(newAnnotations: Annotations): CapturedType = CapturedType(typeProjection, constructor, isMarkedNullable, newAnnotations) + + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = + CapturedType(typeProjection.refine(kotlinTypeRefiner), constructor, isMarkedNullable, annotations) } fun createCapturedType(typeProjection: TypeProjection): KotlinType = CapturedType(typeProjection) diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/ErrorType.kt b/core/descriptors/src/org/jetbrains/kotlin/types/ErrorType.kt index 487f3e5423e..f07d2ede12b 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/ErrorType.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/ErrorType.kt @@ -18,6 +18,8 @@ package org.jetbrains.kotlin.types import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner +import org.jetbrains.kotlin.types.refinement.TypeRefinement open class ErrorType @JvmOverloads internal constructor( override val constructor: TypeConstructor, @@ -35,6 +37,9 @@ open class ErrorType @JvmOverloads internal constructor( override fun makeNullableAsSpecified(newNullability: Boolean): SimpleType = ErrorType(constructor, memberScope, arguments, newNullability) + + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = this } class UnresolvedType( @@ -46,4 +51,7 @@ class UnresolvedType( ) : ErrorType(constructor, memberScope, arguments, isMarkedNullable) { override fun makeNullableAsSpecified(newNullability: Boolean): SimpleType = UnresolvedType(presentableName, constructor, memberScope, arguments, newNullability) + + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = this } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt index 533cc63f58c..bd25acb6458 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt @@ -63,10 +63,13 @@ class IntersectionTypeConstructor(typesToIntersect: Collection) : Ty return intersectedTypes == other.intersectedTypes } + @UseExperimental(TypeRefinement::class) fun createType(): SimpleType = KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope( Annotations.EMPTY, this, listOf(), false, this.createScopeForKotlinType() - ) + ) { kotlinTypeRefiner -> + this.refine(kotlinTypeRefiner).createScopeForKotlinType() + } override fun hashCode(): Int = hashCode diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/KotlinType.kt b/core/descriptors/src/org/jetbrains/kotlin/types/KotlinType.kt index 489ed6bbd89..7f8caf554a0 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/KotlinType.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/KotlinType.kt @@ -21,11 +21,13 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRendererOptions import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.checker.StrictEqualityTypeChecker import org.jetbrains.kotlin.types.model.FlexibleTypeMarker import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.model.SimpleTypeMarker import org.jetbrains.kotlin.types.model.TypeArgumentListMarker +import org.jetbrains.kotlin.types.refinement.TypeRefinement /** * [KotlinType] has only two direct subclasses: [WrappedType] and [UnwrappedType]. @@ -53,6 +55,28 @@ sealed class KotlinType : Annotated, KotlinTypeMarker { abstract fun unwrap(): UnwrappedType + /** + * Returns refined type using passed KotlinTypeRefiner + * + * Refined type has its member scope refined + * + * Note #1: supertypes and type arguments ARE NOT refined! + * + * Note #2: Correct subtyping or equality for refined types from different Refiners *is not guaranteed* + * + * Implementation notice: + * Basically, this is a simple form of double-dispatching, used to incapsulate + * structure of specific type-implementations, which means that compound types most probably would like + * to implement it by recursively calling [refine] on components. + * A very few "basic" types (like [SimpleTypeImpl]) implement it by actually adjusting + * content using passed refiner and other low-level methods + */ + @TypeRefinement + abstract fun refine(kotlinTypeRefiner: KotlinTypeRefiner): KotlinType + + @TypeRefinement + open val hasNotTrivialRefinementFactory: Boolean get() = false + /* '0' means "hashCode wasn't computed" Note #1. We don't use 'null' as a sign of "uncomputed value" to avoid boxing, @@ -139,6 +163,9 @@ sealed class UnwrappedType : KotlinType() { abstract fun makeNullableAsSpecified(newNullability: Boolean): UnwrappedType final override fun unwrap(): UnwrappedType = this + + @TypeRefinement + abstract override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): UnwrappedType } /** @@ -150,6 +177,9 @@ abstract class SimpleType : UnwrappedType(), SimpleTypeMarker, TypeArgumentListM abstract override fun replaceAnnotations(newAnnotations: Annotations): SimpleType abstract override fun makeNullableAsSpecified(newNullability: Boolean): SimpleType + @TypeRefinement + abstract override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): SimpleType + override fun toString(): String { return buildString { for (annotation in annotations) { @@ -185,6 +215,9 @@ abstract class FlexibleType(val lowerBound: SimpleType, val upperBound: SimpleTy override val memberScope: MemberScope get() = delegate.memberScope override fun toString(): String = DescriptorRenderer.DEBUG_TEXT.renderType(this) + + @TypeRefinement + abstract override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): FlexibleType } val KotlinType.isError: Boolean diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeFactory.kt b/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeFactory.kt index 18f20bd57c0..25d43c2c769 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeFactory.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeFactory.kt @@ -16,24 +16,55 @@ package org.jetbrains.kotlin.types -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.getRefinedMemberScopeIfPossible +import org.jetbrains.kotlin.descriptors.impl.getRefinedUnsubstitutedMemberScopeIfPossible import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor +import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.resolve.descriptorUtil.getKotlinTypeRefiner +import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner +import org.jetbrains.kotlin.types.refinement.TypeRefinement +import org.jetbrains.kotlin.utils.addToStdlib.safeAs + +typealias RefinedTypeFactory = (KotlinTypeRefiner) -> SimpleType? object KotlinTypeFactory { - private fun computeMemberScope(constructor: TypeConstructor, arguments: List): MemberScope { - val descriptor = constructor.declarationDescriptor + val EMPTY_REFINED_TYPE_FACTORY: RefinedTypeFactory = { _ -> null } + + @UseExperimental(TypeRefinement::class) + private fun computeMemberScope( + constructor: TypeConstructor, + arguments: List, + kotlinTypeRefiner: KotlinTypeRefiner? = null + ): MemberScope { + val basicDescriptor = constructor.declarationDescriptor + val classId = basicDescriptor.safeAs()?.classId + val descriptor = + if (classId != null) + kotlinTypeRefiner?.findClassAcrossModuleDependencies(classId) ?: basicDescriptor + else basicDescriptor + return when (descriptor) { is TypeParameterDescriptor -> descriptor.getDefaultType().memberScope is ClassDescriptor -> { + val refinedConstructor = + if (descriptor != basicDescriptor) + descriptor.typeConstructor + else + constructor + + val refinerToUse = kotlinTypeRefiner ?: descriptor.module.getKotlinTypeRefiner() if (arguments.isEmpty()) - descriptor.defaultType.memberScope + descriptor.getRefinedUnsubstitutedMemberScopeIfPossible(refinerToUse) else - descriptor.getMemberScope(TypeConstructorSubstitution.create(constructor, arguments)) + // REVIEW + descriptor.getRefinedMemberScopeIfPossible( + TypeConstructorSubstitution.create(refinedConstructor, arguments), + refinerToUse + ) } is TypeAliasDescriptor -> ErrorUtils.createErrorScope("Scope for abbreviation: ${descriptor.name}", true) else -> throw IllegalStateException("Unsupported classifier: $descriptor for constructor: $constructor") @@ -52,12 +83,11 @@ object KotlinTypeFactory { } return simpleTypeWithNonTrivialMemberScope( - annotations, - constructor, - arguments, - nullable, + annotations, constructor, arguments, nullable, computeMemberScope(constructor, arguments) - ) + ) { moduleDescriptor -> + computeMemberScope(constructor, arguments, moduleDescriptor) + } } @JvmStatic @@ -68,7 +98,24 @@ object KotlinTypeFactory { nullable: Boolean, memberScope: MemberScope ): SimpleType = - SimpleTypeImpl(constructor, arguments, nullable, memberScope) + SimpleTypeImpl(constructor, arguments, nullable, memberScope, { memberScope }) + .let { + if (annotations.isEmpty()) + it + else + AnnotatedSimpleType(it, annotations) + } + + @JvmStatic + fun simpleTypeWithNonTrivialMemberScope( + annotations: Annotations, + constructor: TypeConstructor, + arguments: List, + nullable: Boolean, + memberScope: MemberScope, + scopeFactory: (KotlinTypeRefiner) -> MemberScope + ): SimpleType = + SimpleTypeImpl(constructor, arguments, nullable, memberScope, scopeFactory) .let { if (annotations.isEmpty()) it @@ -116,8 +163,12 @@ private class SimpleTypeImpl( override val constructor: TypeConstructor, override val arguments: List, override val isMarkedNullable: Boolean, - override val memberScope: MemberScope + override val memberScope: MemberScope, + private val scopeFactory: (KotlinTypeRefiner) -> MemberScope ) : SimpleType() { + @TypeRefinement + override val hasNotTrivialRefinementFactory: Boolean get() = true + override val annotations: Annotations get() = Annotations.EMPTY override fun replaceAnnotations(newAnnotations: Annotations) = @@ -127,16 +178,26 @@ private class SimpleTypeImpl( AnnotatedSimpleType(this, newAnnotations) override fun makeNullableAsSpecified(newNullability: Boolean) = when { - newNullability == isMarkedNullable -> this - newNullability -> NullableSimpleType(this) - else -> NotNullSimpleType(this) - } + newNullability == isMarkedNullable -> this + newNullability -> NullableSimpleType(this) + else -> NotNullSimpleType(this) + } init { if (memberScope is ErrorUtils.ErrorScope) { throw IllegalStateException("SimpleTypeImpl should not be created for error type: $memberScope\n$constructor") } } + + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): SimpleType { + if (constructor.declarationDescriptor?.module?.getKotlinTypeRefiner() === kotlinTypeRefiner) return this + + return SimpleTypeImpl( + constructor.refine(kotlinTypeRefiner) ?: constructor, + arguments, isMarkedNullable, scopeFactory(kotlinTypeRefiner), scopeFactory + ) + } } abstract class DelegatingSimpleTypeImpl(override val delegate: SimpleType) : DelegatingSimpleType() { @@ -155,14 +216,23 @@ abstract class DelegatingSimpleTypeImpl(override val delegate: SimpleType) : Del private class AnnotatedSimpleType( delegate: SimpleType, override val annotations: Annotations -) : DelegatingSimpleTypeImpl(delegate) +) : DelegatingSimpleTypeImpl(delegate) { + @TypeRefinement + override fun replaceDelegate(delegate: SimpleType) = AnnotatedSimpleType(delegate, annotations) +} private class NullableSimpleType(delegate: SimpleType) : DelegatingSimpleTypeImpl(delegate) { override val isMarkedNullable: Boolean get() = true + + @TypeRefinement + override fun replaceDelegate(delegate: SimpleType) = NullableSimpleType(delegate) } private class NotNullSimpleType(delegate: SimpleType) : DelegatingSimpleTypeImpl(delegate) { override val isMarkedNullable: Boolean get() = false -} \ No newline at end of file + + @TypeRefinement + override fun replaceDelegate(delegate: SimpleType) = NotNullSimpleType(delegate) +} diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt index efd4080bb79..4882e66ef8e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/SpecialTypes.kt @@ -20,9 +20,11 @@ import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.storage.StorageManager +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor import org.jetbrains.kotlin.types.checker.NullabilityChecker import org.jetbrains.kotlin.types.model.DefinitelyNotNullTypeMarker +import org.jetbrains.kotlin.types.refinement.TypeRefinement import org.jetbrains.kotlin.types.typeUtil.canHaveUndefinedNullability abstract class DelegatingSimpleType : SimpleType() { @@ -33,6 +35,13 @@ abstract class DelegatingSimpleType : SimpleType() { override val arguments: List get() = delegate.arguments override val isMarkedNullable: Boolean get() = delegate.isMarkedNullable override val memberScope: MemberScope get() = delegate.memberScope + + @TypeRefinement + abstract fun replaceDelegate(delegate: SimpleType): DelegatingSimpleType + + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): SimpleType = + replaceDelegate(kotlinTypeRefiner.refineType(delegate) as SimpleType) } class AbbreviatedType(override val delegate: SimpleType, val abbreviation: SimpleType) : DelegatingSimpleType() { @@ -43,6 +52,17 @@ class AbbreviatedType(override val delegate: SimpleType, val abbreviation: Simpl override fun makeNullableAsSpecified(newNullability: Boolean) = AbbreviatedType(delegate.makeNullableAsSpecified(newNullability), abbreviation.makeNullableAsSpecified(newNullability)) + + @TypeRefinement + override fun replaceDelegate(delegate: SimpleType) = AbbreviatedType(delegate, abbreviation) + + @TypeRefinement + @UseExperimental(TypeRefinement::class) + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): AbbreviatedType = + AbbreviatedType( + kotlinTypeRefiner.refineType(delegate) as SimpleType, + kotlinTypeRefiner.refineType(abbreviation) as SimpleType + ) } fun KotlinType.getAbbreviatedType(): AbbreviatedType? = unwrap() as? AbbreviatedType @@ -53,12 +73,21 @@ fun SimpleType.withAbbreviation(abbreviatedType: SimpleType): SimpleType { return AbbreviatedType(this, abbreviatedType) } -class LazyWrappedType(storageManager: StorageManager, computation: () -> KotlinType): WrappedType() { +class LazyWrappedType( + private val storageManager: StorageManager, + private val computation: () -> KotlinType +) : WrappedType() { private val lazyValue = storageManager.createLazyValue(computation) override val delegate: KotlinType get() = lazyValue() override fun isComputed(): Boolean = lazyValue.isComputed() + + @TypeRefinement + @UseExperimental(TypeRefinement::class) + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = LazyWrappedType(storageManager) { + kotlinTypeRefiner.refineType(computation()) + } } class DefinitelyNotNullType private constructor(val original: SimpleType) : DelegatingSimpleType(), CustomTypeVariable, @@ -108,6 +137,9 @@ class DefinitelyNotNullType private constructor(val original: SimpleType) : Dele if (newNullability) delegate.makeNullableAsSpecified(newNullability) else this override fun toString(): String = "$delegate!!" + + @TypeRefinement + override fun replaceDelegate(delegate: SimpleType) = DefinitelyNotNullType(delegate) } val KotlinType.isDefinitelyNotNullType: Boolean diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/StarProjectionImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/types/StarProjectionImpl.kt index c9b0a256468..eca738f72cd 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/StarProjectionImpl.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/StarProjectionImpl.kt @@ -16,13 +16,14 @@ package org.jetbrains.kotlin.types -import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner +import org.jetbrains.kotlin.types.refinement.TypeRefinement class StarProjectionImpl( - private val typeParameter: TypeParameterDescriptor + private val typeParameter: TypeParameterDescriptor ) : TypeProjectionBase() { override fun isStarProjection() = true @@ -34,6 +35,11 @@ class StarProjectionImpl( } override fun getType() = _type + + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeProjection = + TypeBasedStarProjectionImpl(kotlinTypeRefiner.refineType(type)) + } fun TypeParameterDescriptor.starProjectionType(): KotlinType { @@ -58,4 +64,8 @@ class TypeBasedStarProjectionImpl( override fun getProjectionKind() = Variance.OUT_VARIANCE override fun getType() = _type + + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeProjection = + TypeBasedStarProjectionImpl(kotlinTypeRefiner.refineType(_type)) } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/StubType.kt b/core/descriptors/src/org/jetbrains/kotlin/types/StubType.kt index 9096e70788f..85e3d81a2bc 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/StubType.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/StubType.kt @@ -7,7 +7,9 @@ package org.jetbrains.kotlin.types import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.model.StubTypeMarker +import org.jetbrains.kotlin.types.refinement.TypeRefinement // This type is used as a stub for postponed type variables, which are important for coroutine inference class StubType( @@ -37,4 +39,7 @@ class StubType( override fun toString(): String { return "NonFixed: $originalTypeVariable" } -} \ No newline at end of file + + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = this +} diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeProjection.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeProjection.java index 24a4aafe6ed..b31841fd09e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeProjection.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeProjection.java @@ -17,7 +17,9 @@ package org.jetbrains.kotlin.types; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner; import org.jetbrains.kotlin.types.model.TypeArgumentMarker; +import org.jetbrains.kotlin.types.refinement.TypeRefinement; public interface TypeProjection extends TypeArgumentMarker { @NotNull @@ -27,4 +29,8 @@ public interface TypeProjection extends TypeArgumentMarker { KotlinType getType(); boolean isStarProjection(); + + @NotNull + @TypeRefinement + TypeProjection refine(@NotNull KotlinTypeRefiner kotlinTypeRefiner); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeProjectionImpl.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeProjectionImpl.java index 920bbe4194c..9ae2b9c550e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeProjectionImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeProjectionImpl.java @@ -17,6 +17,8 @@ package org.jetbrains.kotlin.types; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner; +import org.jetbrains.kotlin.types.refinement.TypeRefinement; public class TypeProjectionImpl extends TypeProjectionBase { private final Variance projection; @@ -47,4 +49,11 @@ public class TypeProjectionImpl extends TypeProjectionBase { public boolean isStarProjection() { return false; } + + @NotNull + @Override + @TypeRefinement + public TypeProjection refine(@NotNull KotlinTypeRefiner kotlinTypeRefiner) { + return new TypeProjectionImpl(projection, kotlinTypeRefiner.refineType(type)); + } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java index 66e37d9a706..3c38b061231 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java @@ -22,7 +22,9 @@ import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor; import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor; import org.jetbrains.kotlin.resolve.scopes.MemberScope; import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner; import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor; +import org.jetbrains.kotlin.types.refinement.TypeRefinement; import java.util.*; @@ -60,6 +62,20 @@ public class TypeUtils { public String toString() { return name; } + + @NotNull + @Override + @TypeRefinement + public DelegatingSimpleType replaceDelegate(@NotNull SimpleType delegate) { + throw new IllegalStateException(name); + } + + @NotNull + @Override + @TypeRefinement + public SpecialType refine(@NotNull KotlinTypeRefiner kotlinTypeRefiner) { + return this; + } } @NotNull @@ -185,7 +201,10 @@ public class TypeUtils { } @NotNull - public static SimpleType makeUnsubstitutedType(ClassifierDescriptor classifierDescriptor, MemberScope unsubstitutedMemberScope) { + public static SimpleType makeUnsubstitutedType( + ClassifierDescriptor classifierDescriptor, MemberScope unsubstitutedMemberScope, + Function1 scopeFactory + ) { if (ErrorUtils.isError(classifierDescriptor)) { return ErrorUtils.createErrorType("Unsubstituted type for " + classifierDescriptor); } @@ -196,7 +215,8 @@ public class TypeUtils { typeConstructor, arguments, false, - unsubstitutedMemberScope + unsubstitutedMemberScope, + scopeFactory ); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeWithEnhancement.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeWithEnhancement.kt index d1a6c5a8e60..e6729c60264 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeWithEnhancement.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeWithEnhancement.kt @@ -19,6 +19,8 @@ package org.jetbrains.kotlin.types import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRendererOptions +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner +import org.jetbrains.kotlin.types.refinement.TypeRefinement interface TypeWithEnhancement { val origin: UnwrappedType @@ -38,6 +40,17 @@ class SimpleTypeWithEnhancement( override fun makeNullableAsSpecified(newNullability: Boolean): SimpleType = origin.makeNullableAsSpecified(newNullability).wrapEnhancement(enhancement.unwrap().makeNullableAsSpecified(newNullability)) as SimpleType + + @TypeRefinement + override fun replaceDelegate(delegate: SimpleType) = SimpleTypeWithEnhancement(delegate, enhancement) + + @TypeRefinement + @UseExperimental(TypeRefinement::class) + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): SimpleTypeWithEnhancement = + SimpleTypeWithEnhancement( + kotlinTypeRefiner.refineType(delegate) as SimpleType, + kotlinTypeRefiner.refineType(enhancement) + ) } class FlexibleTypeWithEnhancement( @@ -60,6 +73,14 @@ class FlexibleTypeWithEnhancement( } override val delegate: SimpleType get() = origin.delegate + + @TypeRefinement + @UseExperimental(TypeRefinement::class) + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = + FlexibleTypeWithEnhancement( + kotlinTypeRefiner.refineType(origin) as FlexibleType, + kotlinTypeRefiner.refineType(enhancement) + ) } fun KotlinType.getEnhancement(): KotlinType? = when (this) { diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt index 94da3aa9416..39a31919b33 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/NewCapturedType.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.model.CaptureStatus import org.jetbrains.kotlin.types.model.CapturedTypeMarker +import org.jetbrains.kotlin.types.refinement.TypeRefinement import org.jetbrains.kotlin.types.typeUtil.asTypeProjection import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.utils.DO_NOTHING_2 @@ -139,6 +140,16 @@ class NewCapturedType( override fun makeNullableAsSpecified(newNullability: Boolean) = NewCapturedType(captureStatus, constructor, lowerType, annotations, newNullability) + + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = + NewCapturedType( + captureStatus, + constructor.refine(kotlinTypeRefiner), + lowerType?.let { kotlinTypeRefiner.refineType(it).unwrap() }, + annotations, + isMarkedNullable + ) } class NewCapturedTypeConstructor(override val projection: TypeProjection, private var supertypes: List? = null) : diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/dynamicTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/types/dynamicTypes.kt index 0fd5245fa39..7722549a206 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/dynamicTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/dynamicTypes.kt @@ -18,12 +18,13 @@ package org.jetbrains.kotlin.types import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.container.DefaultImplementation -import org.jetbrains.kotlin.container.PlatformExtensionsClashResolver import org.jetbrains.kotlin.container.PlatformSpecificExtension import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRendererOptions +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.model.DynamicTypeMarker +import org.jetbrains.kotlin.types.refinement.TypeRefinement import org.jetbrains.kotlin.types.typeUtil.builtIns @DefaultImplementation(impl = DynamicTypesSettings::class) @@ -55,4 +56,7 @@ class DynamicType( override fun replaceAnnotations(newAnnotations: Annotations): DynamicType = DynamicType(delegate.builtIns, newAnnotations) override fun render(renderer: DescriptorRenderer, options: DescriptorRendererOptions): String = "dynamic" + + @TypeRefinement + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = this } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt index fc4b57f70aa..37c2f83f3cb 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt @@ -22,6 +22,8 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRendererOptions import org.jetbrains.kotlin.types.checker.ErrorTypesAreEqualToAnything import org.jetbrains.kotlin.types.checker.KotlinTypeChecker +import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner +import org.jetbrains.kotlin.types.refinement.TypeRefinement import org.jetbrains.kotlin.types.typeUtil.builtIns @@ -134,4 +136,12 @@ class FlexibleTypeImpl(lowerBound: SimpleType, upperBound: SimpleType) : Flexibl override fun makeNullableAsSpecified(newNullability: Boolean): UnwrappedType = KotlinTypeFactory.flexibleType(lowerBound.makeNullableAsSpecified(newNullability), upperBound.makeNullableAsSpecified(newNullability)) + + @TypeRefinement + @UseExperimental(TypeRefinement::class) + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = + KotlinTypeFactory.flexibleType( + kotlinTypeRefiner.refineType(lowerBound) as SimpleType, + kotlinTypeRefiner.refineType(upperBound) as SimpleType + ) as FlexibleType }