[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
This commit is contained in:
Denis Zharkov
2019-05-07 16:27:50 +03:00
committed by Dmitry Savvinov
parent 04717b57c9
commit 9c27abde7f
7 changed files with 117 additions and 62 deletions
@@ -580,7 +580,7 @@ open class WrappedClassDescriptor(
private val _defaultType: SimpleType by lazy { 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 override fun getDefaultType(): SimpleType = _defaultType
@@ -691,7 +691,7 @@ open class WrappedEnumEntryDescriptor(
private val _defaultType: SimpleType by lazy { 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 override fun getDefaultType(): SimpleType = _defaultType
@@ -102,8 +102,16 @@ internal object RawSubstitution : TypeSubstitution() {
return when (declaration) { return when (declaration) {
is TypeParameterDescriptor -> eraseType(declaration.getErasedUpperBound()) is TypeParameterDescriptor -> eraseType(declaration.getErasedUpperBound())
is ClassDescriptor -> { 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 (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) { if (isRawL || isRawU) {
RawTypeImpl(lower, upper) RawTypeImpl(lower, upper)
@@ -135,17 +143,18 @@ internal object RawSubstitution : TypeSubstitution() {
val memberScope = declaration.getMemberScope(RawSubstitution) val memberScope = declaration.getMemberScope(RawSubstitution)
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope( return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
type.annotations, type.constructor, type.annotations, declaration.typeConstructor,
type.constructor.parameters.map { parameter -> declaration.typeConstructor.parameters.map { parameter ->
computeProjection(parameter, attr) computeProjection(parameter, attr)
}, },
type.isMarkedNullable, memberScope type.isMarkedNullable, memberScope
) factory@{ kotlinTypeRefiner -> ) 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 eraseInflexibleBasedOnClassDescriptor(type, refinedClassDescriptor, attr).first
.findClassAcrossModuleDependencies(classId)
?.getRefinedMemberScopeIfPossible(RawSubstitution, moduleDescriptor) ?: memberScope
} to true } to true
} }
@@ -46,16 +46,30 @@ public abstract class AbstractClassDescriptor extends ModuleAwareClassDescriptor
public SimpleType invoke() { public SimpleType invoke() {
return TypeUtils.makeUnsubstitutedType( return TypeUtils.makeUnsubstitutedType(
AbstractClassDescriptor.this, getUnsubstitutedMemberScope(), AbstractClassDescriptor.this, getUnsubstitutedMemberScope(),
new Function1<KotlinTypeRefiner, MemberScope>() { new Function1<KotlinTypeRefiner, SimpleType>() {
@Override @Override
public MemberScope invoke(KotlinTypeRefiner kotlinTypeRefiner) { public SimpleType invoke(KotlinTypeRefiner kotlinTypeRefiner) {
ClassDescriptor descriptor = kotlinTypeRefiner.refineDescriptor(AbstractClassDescriptor.this); ClassifierDescriptor descriptor = kotlinTypeRefiner.refineDescriptor(AbstractClassDescriptor.this);
if (descriptor == null) return getUnsubstitutedMemberScope(kotlinTypeRefiner); // 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) { 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();
} }
} }
); );
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
import org.jetbrains.kotlin.types.refinement.TypeRefinement import org.jetbrains.kotlin.types.refinement.TypeRefinement
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
abstract class AbstractTypeAliasDescriptor( abstract class AbstractTypeAliasDescriptor(
containingDeclaration: DeclarationDescriptor, containingDeclaration: DeclarationDescriptor,
@@ -96,11 +95,7 @@ abstract class AbstractTypeAliasDescriptor(
@UseExperimental(TypeRefinement::class) @UseExperimental(TypeRefinement::class)
protected fun computeDefaultType(): SimpleType = protected fun computeDefaultType(): SimpleType =
TypeUtils.makeUnsubstitutedType(this, classDescriptor?.unsubstitutedMemberScope ?: MemberScope.Empty) { kotlinTypeRefiner -> TypeUtils.makeUnsubstitutedType(this, classDescriptor?.unsubstitutedMemberScope ?: MemberScope.Empty) { kotlinTypeRefiner ->
classDescriptor kotlinTypeRefiner.refineDescriptor(this)?.defaultType
?.let { kotlinTypeRefiner.refineDescriptor(it) }
?.safeAs<ClassDescriptor>()
?.unsubstitutedMemberScope
?: MemberScope.Empty
} }
private val typeConstructor = object : TypeConstructor { 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 // There must be @TypeRefinement, but there is a bug with anonymous objects and experimental annotations
// See KT-31728 // See KT-31728
@UseExperimental(TypeRefinement::class) @UseExperimental(TypeRefinement::class)
override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeConstructor? = this override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeConstructor = this
} }
} }
@@ -68,7 +68,7 @@ class IntersectionTypeConstructor(typesToIntersect: Collection<KotlinType>) : Ty
KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope( KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
Annotations.EMPTY, this, listOf(), false, this.createScopeForKotlinType() Annotations.EMPTY, this, listOf(), false, this.createScopeForKotlinType()
) { kotlinTypeRefiner -> ) { kotlinTypeRefiner ->
this.refine(kotlinTypeRefiner).createScopeForKotlinType() this.refine(kotlinTypeRefiner).createType()
} }
override fun hashCode(): Int = hashCode override fun hashCode(): Int = hashCode
@@ -16,18 +16,18 @@
package org.jetbrains.kotlin.types 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.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.getRefinedMemberScopeIfPossible import org.jetbrains.kotlin.descriptors.impl.getRefinedMemberScopeIfPossible
import org.jetbrains.kotlin.descriptors.impl.getRefinedUnsubstitutedMemberScopeIfPossible import org.jetbrains.kotlin.descriptors.impl.getRefinedUnsubstitutedMemberScopeIfPossible
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor 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.getKotlinTypeRefiner
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
import org.jetbrains.kotlin.types.refinement.TypeRefinement import org.jetbrains.kotlin.types.refinement.TypeRefinement
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
typealias RefinedTypeFactory = (KotlinTypeRefiner) -> SimpleType? typealias RefinedTypeFactory = (KotlinTypeRefiner) -> SimpleType?
@@ -40,29 +40,17 @@ object KotlinTypeFactory {
arguments: List<TypeProjection>, arguments: List<TypeProjection>,
kotlinTypeRefiner: KotlinTypeRefiner? = null kotlinTypeRefiner: KotlinTypeRefiner? = null
): MemberScope { ): MemberScope {
val basicDescriptor = constructor.declarationDescriptor val descriptor = constructor.declarationDescriptor
val classId = basicDescriptor.safeAs<ClassifierDescriptorWithTypeParameters>()?.classId
val descriptor =
if (classId != null)
kotlinTypeRefiner?.findClassAcrossModuleDependencies(classId) ?: basicDescriptor
else basicDescriptor
return when (descriptor) { return when (descriptor) {
is TypeParameterDescriptor -> descriptor.getDefaultType().memberScope is TypeParameterDescriptor -> descriptor.getDefaultType().memberScope
is ClassDescriptor -> { is ClassDescriptor -> {
val refinedConstructor =
if (descriptor != basicDescriptor)
descriptor.typeConstructor
else
constructor
val refinerToUse = kotlinTypeRefiner ?: descriptor.module.getKotlinTypeRefiner() val refinerToUse = kotlinTypeRefiner ?: descriptor.module.getKotlinTypeRefiner()
if (arguments.isEmpty()) if (arguments.isEmpty())
descriptor.getRefinedUnsubstitutedMemberScopeIfPossible(refinerToUse) descriptor.getRefinedUnsubstitutedMemberScopeIfPossible(refinerToUse)
else else
// REVIEW // REVIEW
descriptor.getRefinedMemberScopeIfPossible( descriptor.getRefinedMemberScopeIfPossible(
TypeConstructorSubstitution.create(refinedConstructor, arguments), TypeConstructorSubstitution.create(constructor, arguments),
refinerToUse refinerToUse
) )
} }
@@ -72,11 +60,14 @@ object KotlinTypeFactory {
} }
@JvmStatic @JvmStatic
@JvmOverloads
@UseExperimental(TypeRefinement::class)
fun simpleType( fun simpleType(
annotations: Annotations, annotations: Annotations,
constructor: TypeConstructor, constructor: TypeConstructor,
arguments: List<TypeProjection>, arguments: List<TypeProjection>,
nullable: Boolean nullable: Boolean,
kotlinTypeRefiner: KotlinTypeRefiner? = null
): SimpleType { ): SimpleType {
if (annotations.isEmpty() && arguments.isEmpty() && !nullable && constructor.declarationDescriptor != null) { if (annotations.isEmpty() && arguments.isEmpty() && !nullable && constructor.declarationDescriptor != null) {
return constructor.declarationDescriptor!!.defaultType return constructor.declarationDescriptor!!.defaultType
@@ -84,13 +75,45 @@ object KotlinTypeFactory {
return simpleTypeWithNonTrivialMemberScope( return simpleTypeWithNonTrivialMemberScope(
annotations, constructor, arguments, nullable, annotations, constructor, arguments, nullable,
computeMemberScope(constructor, arguments) computeMemberScope(constructor, arguments, kotlinTypeRefiner)
) { moduleDescriptor -> ) f@{ refiner ->
computeMemberScope(constructor, arguments, moduleDescriptor) val expandedTypeOrRefinedConstructor = refineConstructor(constructor, refiner, arguments) ?: return@f null
expandedTypeOrRefinedConstructor.expandedType?.let { return@f it }
simpleType(annotations, expandedTypeOrRefinedConstructor.refinedConstructor!!, arguments, nullable, refiner)
} }
} }
@JvmStatic @JvmStatic
fun TypeAliasDescriptor.computeExpandedType(arguments: List<TypeProjection>): 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<TypeProjection>
): 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( fun simpleTypeWithNonTrivialMemberScope(
annotations: Annotations, annotations: Annotations,
constructor: TypeConstructor, constructor: TypeConstructor,
@@ -98,13 +121,23 @@ object KotlinTypeFactory {
nullable: Boolean, nullable: Boolean,
memberScope: MemberScope memberScope: MemberScope
): SimpleType = ): SimpleType =
SimpleTypeImpl(constructor, arguments, nullable, memberScope, { memberScope }) SimpleTypeImpl(constructor, arguments, nullable, memberScope) { kotlinTypeRefiner ->
.let { val expandedTypeOrRefinedConstructor = refineConstructor(constructor, kotlinTypeRefiner, arguments) ?: return@SimpleTypeImpl null
if (annotations.isEmpty()) expandedTypeOrRefinedConstructor.expandedType?.let { return@SimpleTypeImpl it }
it
else simpleTypeWithNonTrivialMemberScope(
AnnotatedSimpleType(it, annotations) annotations,
} expandedTypeOrRefinedConstructor.refinedConstructor!!,
arguments,
nullable,
memberScope
)
}.let {
if (annotations.isEmpty())
it
else
AnnotatedSimpleType(it, annotations)
}
@JvmStatic @JvmStatic
fun simpleTypeWithNonTrivialMemberScope( fun simpleTypeWithNonTrivialMemberScope(
@@ -113,9 +146,9 @@ object KotlinTypeFactory {
arguments: List<TypeProjection>, arguments: List<TypeProjection>,
nullable: Boolean, nullable: Boolean,
memberScope: MemberScope, memberScope: MemberScope,
scopeFactory: (KotlinTypeRefiner) -> MemberScope refinedTypeFactory: RefinedTypeFactory
): SimpleType = ): SimpleType =
SimpleTypeImpl(constructor, arguments, nullable, memberScope, scopeFactory) SimpleTypeImpl(constructor, arguments, nullable, memberScope, refinedTypeFactory)
.let { .let {
if (annotations.isEmpty()) if (annotations.isEmpty())
it it
@@ -164,7 +197,7 @@ private class SimpleTypeImpl(
override val arguments: List<TypeProjection>, override val arguments: List<TypeProjection>,
override val isMarkedNullable: Boolean, override val isMarkedNullable: Boolean,
override val memberScope: MemberScope, override val memberScope: MemberScope,
private val scopeFactory: (KotlinTypeRefiner) -> MemberScope private val refinedTypeFactory: RefinedTypeFactory
) : SimpleType() { ) : SimpleType() {
@TypeRefinement @TypeRefinement
override val hasNotTrivialRefinementFactory: Boolean get() = true override val hasNotTrivialRefinementFactory: Boolean get() = true
@@ -191,12 +224,7 @@ private class SimpleTypeImpl(
@TypeRefinement @TypeRefinement
override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): SimpleType { override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): SimpleType {
if (constructor.declarationDescriptor?.module?.getKotlinTypeRefiner() === kotlinTypeRefiner) return this return refinedTypeFactory(kotlinTypeRefiner) ?: this
return SimpleTypeImpl(
constructor.refine(kotlinTypeRefiner) ?: constructor,
arguments, isMarkedNullable, scopeFactory(kotlinTypeRefiner), scopeFactory
)
} }
} }
@@ -203,12 +203,21 @@ public class TypeUtils {
@NotNull @NotNull
public static SimpleType makeUnsubstitutedType( public static SimpleType makeUnsubstitutedType(
ClassifierDescriptor classifierDescriptor, MemberScope unsubstitutedMemberScope, ClassifierDescriptor classifierDescriptor, MemberScope unsubstitutedMemberScope,
Function1<KotlinTypeRefiner, MemberScope> scopeFactory Function1<KotlinTypeRefiner, SimpleType> refinedTypeFactory
) { ) {
if (ErrorUtils.isError(classifierDescriptor)) { if (ErrorUtils.isError(classifierDescriptor)) {
return ErrorUtils.createErrorType("Unsubstituted type for " + classifierDescriptor); return ErrorUtils.createErrorType("Unsubstituted type for " + classifierDescriptor);
} }
TypeConstructor typeConstructor = classifierDescriptor.getTypeConstructor(); TypeConstructor typeConstructor = classifierDescriptor.getTypeConstructor();
return makeUnsubstitutedType(typeConstructor, unsubstitutedMemberScope, refinedTypeFactory);
}
@NotNull
public static SimpleType makeUnsubstitutedType(
@NotNull TypeConstructor typeConstructor,
@NotNull MemberScope unsubstitutedMemberScope,
@NotNull Function1<KotlinTypeRefiner, SimpleType> refinedTypeFactory
) {
List<TypeProjection> arguments = getDefaultTypeProjections(typeConstructor.getParameters()); List<TypeProjection> arguments = getDefaultTypeProjections(typeConstructor.getParameters());
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope( return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
Annotations.Companion.getEMPTY(), Annotations.Companion.getEMPTY(),
@@ -216,7 +225,7 @@ public class TypeUtils {
arguments, arguments,
false, false,
unsubstitutedMemberScope, unsubstitutedMemberScope,
scopeFactory refinedTypeFactory
); );
} }