From 9c27abde7f3312b5949722bb2d1ed549865a9e11 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 7 May 2019 16:27:50 +0300 Subject: [PATCH] [API Usage] Support type refinement from expect class to type aliases It's necessary when expect class is actualized via typealias To support it properly, we need to return AbbriviatedType instead of SimpleTypeImpl, thus scopeFactory is not enough anymore --- .../common/descriptors/WrappedDescriptors.kt | 4 +- .../kotlin/load/java/lazy/types/RawType.kt | 23 ++-- .../impl/AbstractClassDescriptor.java | 26 +++-- .../impl/AbstractTypeAliasDescriptor.kt | 9 +- .../types/IntersectionTypeConstructor.kt | 2 +- .../kotlin/types/KotlinTypeFactory.kt | 102 +++++++++++------- .../org/jetbrains/kotlin/types/TypeUtils.java | 13 ++- 7 files changed, 117 insertions(+), 62 deletions(-) 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 b68847ab0b1..c1ca78317af 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) { unsubstitutedMemberScope } + TypeUtils.makeUnsubstitutedType(this, unsubstitutedMemberScope, KotlinTypeFactory.EMPTY_REFINED_TYPE_FACTORY) } override fun getDefaultType(): SimpleType = _defaultType @@ -691,7 +691,7 @@ open class WrappedEnumEntryDescriptor( private val _defaultType: SimpleType by lazy { - TypeUtils.makeUnsubstitutedType(this, unsubstitutedMemberScope) { unsubstitutedMemberScope } + TypeUtils.makeUnsubstitutedType(this, unsubstitutedMemberScope, KotlinTypeFactory.EMPTY_REFINED_TYPE_FACTORY) } 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 6905e443dc5..e29b6fd343d 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 @@ -102,8 +102,16 @@ internal object RawSubstitution : TypeSubstitution() { return when (declaration) { is TypeParameterDescriptor -> eraseType(declaration.getErasedUpperBound()) is ClassDescriptor -> { + val declarationForUpper = + type.upperIfFlexible().constructor.declarationDescriptor + + check(declarationForUpper is ClassDescriptor) { + "For some reason declaration for upper bound is not a class " + + "but \"$declarationForUpper\" while for lower it's \"$declaration\"" + } + val (lower, isRawL) = eraseInflexibleBasedOnClassDescriptor(type.lowerIfFlexible(), declaration, lowerTypeAttr) - val (upper, isRawU) = eraseInflexibleBasedOnClassDescriptor(type.upperIfFlexible(), declaration, upperTypeAttr) + val (upper, isRawU) = eraseInflexibleBasedOnClassDescriptor(type.upperIfFlexible(), declarationForUpper, upperTypeAttr) if (isRawL || isRawU) { RawTypeImpl(lower, upper) @@ -135,17 +143,18 @@ internal object RawSubstitution : TypeSubstitution() { val memberScope = declaration.getMemberScope(RawSubstitution) return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope( - type.annotations, type.constructor, - type.constructor.parameters.map { parameter -> + type.annotations, declaration.typeConstructor, + declaration.typeConstructor.parameters.map { parameter -> computeProjection(parameter, attr) }, type.isMarkedNullable, memberScope ) factory@{ kotlinTypeRefiner -> - val classId = (declaration as? ClassDescriptor)?.classId ?: return@factory memberScope + val classId = (declaration as? ClassDescriptor)?.classId ?: return@factory null + @UseExperimental(TypeRefinement::class) + val refinedClassDescriptor = kotlinTypeRefiner.findClassAcrossModuleDependencies(classId) ?: return@factory null + if (refinedClassDescriptor == declaration) return@factory null - kotlinTypeRefiner - .findClassAcrossModuleDependencies(classId) - ?.getRefinedMemberScopeIfPossible(RawSubstitution, moduleDescriptor) ?: memberScope + eraseInflexibleBasedOnClassDescriptor(type, refinedClassDescriptor, attr).first } to true } 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 57bbc594436..a45eb8853cb 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractClassDescriptor.java @@ -46,16 +46,30 @@ public abstract class AbstractClassDescriptor extends ModuleAwareClassDescriptor public SimpleType invoke() { return TypeUtils.makeUnsubstitutedType( AbstractClassDescriptor.this, getUnsubstitutedMemberScope(), - new Function1() { + new Function1() { @Override - public MemberScope invoke(KotlinTypeRefiner kotlinTypeRefiner) { - ClassDescriptor descriptor = kotlinTypeRefiner.refineDescriptor(AbstractClassDescriptor.this); - if (descriptor == null) return getUnsubstitutedMemberScope(kotlinTypeRefiner); + public SimpleType invoke(KotlinTypeRefiner kotlinTypeRefiner) { + ClassifierDescriptor descriptor = kotlinTypeRefiner.refineDescriptor(AbstractClassDescriptor.this); + // If we've refined descriptor + if (descriptor == null) return defaultType.invoke(); + + if (descriptor instanceof TypeAliasDescriptor) { + return KotlinTypeFactory.computeExpandedType( + (TypeAliasDescriptor) descriptor, + TypeUtils.getDefaultTypeProjections(descriptor.getTypeConstructor().getParameters()) + ); + } if (descriptor instanceof ModuleAwareClassDescriptor) { - return ((ModuleAwareClassDescriptor) descriptor).getUnsubstitutedMemberScope(kotlinTypeRefiner); + TypeConstructor refinedConstructor = descriptor.getTypeConstructor().refine(kotlinTypeRefiner); + return TypeUtils.makeUnsubstitutedType( + refinedConstructor, + ((ModuleAwareClassDescriptor) descriptor).getUnsubstitutedMemberScope(kotlinTypeRefiner), + this + ); } - return descriptor.getUnsubstitutedMemberScope(); + + return descriptor.getDefaultType(); } } ); 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 e27714124ba..69ee9878b10 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeAliasDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeAliasDescriptor.kt @@ -27,7 +27,6 @@ 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, @@ -96,11 +95,7 @@ abstract class AbstractTypeAliasDescriptor( @UseExperimental(TypeRefinement::class) protected fun computeDefaultType(): SimpleType = TypeUtils.makeUnsubstitutedType(this, classDescriptor?.unsubstitutedMemberScope ?: MemberScope.Empty) { kotlinTypeRefiner -> - classDescriptor - ?.let { kotlinTypeRefiner.refineDescriptor(it) } - ?.safeAs() - ?.unsubstitutedMemberScope - ?: MemberScope.Empty + kotlinTypeRefiner.refineDescriptor(this)?.defaultType } private val typeConstructor = object : TypeConstructor { @@ -127,6 +122,6 @@ abstract class AbstractTypeAliasDescriptor( // There must be @TypeRefinement, but there is a bug with anonymous objects and experimental annotations // See KT-31728 @UseExperimental(TypeRefinement::class) - override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeConstructor? = this + override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeConstructor = this } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt index bd25acb6458..a5871b9b762 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt @@ -68,7 +68,7 @@ class IntersectionTypeConstructor(typesToIntersect: Collection) : Ty KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope( Annotations.EMPTY, this, listOf(), false, this.createScopeForKotlinType() ) { kotlinTypeRefiner -> - this.refine(kotlinTypeRefiner).createScopeForKotlinType() + this.refine(kotlinTypeRefiner).createType() } override fun hashCode(): Int = hashCode diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeFactory.kt b/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeFactory.kt index 25d43c2c769..78607a33815 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeFactory.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/KotlinTypeFactory.kt @@ -16,18 +16,18 @@ package org.jetbrains.kotlin.types -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor 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.KotlinTypeRefiner import org.jetbrains.kotlin.types.refinement.TypeRefinement -import org.jetbrains.kotlin.utils.addToStdlib.safeAs typealias RefinedTypeFactory = (KotlinTypeRefiner) -> SimpleType? @@ -40,29 +40,17 @@ object KotlinTypeFactory { 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 - + val descriptor = constructor.declarationDescriptor 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.getRefinedUnsubstitutedMemberScopeIfPossible(refinerToUse) else // REVIEW descriptor.getRefinedMemberScopeIfPossible( - TypeConstructorSubstitution.create(refinedConstructor, arguments), + TypeConstructorSubstitution.create(constructor, arguments), refinerToUse ) } @@ -72,11 +60,14 @@ object KotlinTypeFactory { } @JvmStatic + @JvmOverloads + @UseExperimental(TypeRefinement::class) fun simpleType( annotations: Annotations, constructor: TypeConstructor, arguments: List, - nullable: Boolean + nullable: Boolean, + kotlinTypeRefiner: KotlinTypeRefiner? = null ): SimpleType { if (annotations.isEmpty() && arguments.isEmpty() && !nullable && constructor.declarationDescriptor != null) { return constructor.declarationDescriptor!!.defaultType @@ -84,13 +75,45 @@ object KotlinTypeFactory { return simpleTypeWithNonTrivialMemberScope( annotations, constructor, arguments, nullable, - computeMemberScope(constructor, arguments) - ) { moduleDescriptor -> - computeMemberScope(constructor, arguments, moduleDescriptor) + computeMemberScope(constructor, arguments, kotlinTypeRefiner) + ) f@{ refiner -> + val expandedTypeOrRefinedConstructor = refineConstructor(constructor, refiner, arguments) ?: return@f null + expandedTypeOrRefinedConstructor.expandedType?.let { return@f it } + + simpleType(annotations, expandedTypeOrRefinedConstructor.refinedConstructor!!, arguments, nullable, refiner) } } @JvmStatic + fun TypeAliasDescriptor.computeExpandedType(arguments: List): SimpleType { + return TypeAliasExpander(TypeAliasExpansionReportStrategy.DO_NOTHING, false).expand( + TypeAliasExpansion.create(null, this, arguments), Annotations.EMPTY + ) + } + + @TypeRefinement + private fun refineConstructor( + constructor: TypeConstructor, + kotlinTypeRefiner: KotlinTypeRefiner, + arguments: List + ): ExpandedTypeOrRefinedConstructor? { + val basicDescriptor = constructor.declarationDescriptor + val descriptor = basicDescriptor?.let { kotlinTypeRefiner.refineDescriptor(it) } ?: return null + + if (descriptor == basicDescriptor) return null + + if (descriptor is TypeAliasDescriptor) { + return ExpandedTypeOrRefinedConstructor(descriptor.computeExpandedType(arguments), null) + } + + val refinedConstructor = descriptor.typeConstructor.refine(kotlinTypeRefiner) + return ExpandedTypeOrRefinedConstructor(null, refinedConstructor) + } + + private class ExpandedTypeOrRefinedConstructor(val expandedType: SimpleType?, val refinedConstructor: TypeConstructor?) + + @JvmStatic + @UseExperimental(TypeRefinement::class) fun simpleTypeWithNonTrivialMemberScope( annotations: Annotations, constructor: TypeConstructor, @@ -98,13 +121,23 @@ object KotlinTypeFactory { nullable: Boolean, memberScope: MemberScope ): SimpleType = - SimpleTypeImpl(constructor, arguments, nullable, memberScope, { memberScope }) - .let { - if (annotations.isEmpty()) - it - else - AnnotatedSimpleType(it, annotations) - } + SimpleTypeImpl(constructor, arguments, nullable, memberScope) { kotlinTypeRefiner -> + val expandedTypeOrRefinedConstructor = refineConstructor(constructor, kotlinTypeRefiner, arguments) ?: return@SimpleTypeImpl null + expandedTypeOrRefinedConstructor.expandedType?.let { return@SimpleTypeImpl it } + + simpleTypeWithNonTrivialMemberScope( + annotations, + expandedTypeOrRefinedConstructor.refinedConstructor!!, + arguments, + nullable, + memberScope + ) + }.let { + if (annotations.isEmpty()) + it + else + AnnotatedSimpleType(it, annotations) + } @JvmStatic fun simpleTypeWithNonTrivialMemberScope( @@ -113,9 +146,9 @@ object KotlinTypeFactory { arguments: List, nullable: Boolean, memberScope: MemberScope, - scopeFactory: (KotlinTypeRefiner) -> MemberScope + refinedTypeFactory: RefinedTypeFactory ): SimpleType = - SimpleTypeImpl(constructor, arguments, nullable, memberScope, scopeFactory) + SimpleTypeImpl(constructor, arguments, nullable, memberScope, refinedTypeFactory) .let { if (annotations.isEmpty()) it @@ -164,7 +197,7 @@ private class SimpleTypeImpl( override val arguments: List, override val isMarkedNullable: Boolean, override val memberScope: MemberScope, - private val scopeFactory: (KotlinTypeRefiner) -> MemberScope + private val refinedTypeFactory: RefinedTypeFactory ) : SimpleType() { @TypeRefinement override val hasNotTrivialRefinementFactory: Boolean get() = true @@ -191,12 +224,7 @@ private class SimpleTypeImpl( @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 - ) + return refinedTypeFactory(kotlinTypeRefiner) ?: this } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java index 3c38b061231..1031c466a63 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java @@ -203,12 +203,21 @@ public class TypeUtils { @NotNull public static SimpleType makeUnsubstitutedType( ClassifierDescriptor classifierDescriptor, MemberScope unsubstitutedMemberScope, - Function1 scopeFactory + Function1 refinedTypeFactory ) { if (ErrorUtils.isError(classifierDescriptor)) { return ErrorUtils.createErrorType("Unsubstituted type for " + classifierDescriptor); } TypeConstructor typeConstructor = classifierDescriptor.getTypeConstructor(); + return makeUnsubstitutedType(typeConstructor, unsubstitutedMemberScope, refinedTypeFactory); + } + + @NotNull + public static SimpleType makeUnsubstitutedType( + @NotNull TypeConstructor typeConstructor, + @NotNull MemberScope unsubstitutedMemberScope, + @NotNull Function1 refinedTypeFactory + ) { List arguments = getDefaultTypeProjections(typeConstructor.getParameters()); return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope( Annotations.Companion.getEMPTY(), @@ -216,7 +225,7 @@ public class TypeUtils { arguments, false, unsubstitutedMemberScope, - scopeFactory + refinedTypeFactory ); }