[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 {
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
@@ -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
}
@@ -46,16 +46,30 @@ public abstract class AbstractClassDescriptor extends ModuleAwareClassDescriptor
public SimpleType invoke() {
return TypeUtils.makeUnsubstitutedType(
AbstractClassDescriptor.this, getUnsubstitutedMemberScope(),
new Function1<KotlinTypeRefiner, MemberScope>() {
new Function1<KotlinTypeRefiner, SimpleType>() {
@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();
}
}
);
@@ -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<ClassDescriptor>()
?.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
}
}
@@ -68,7 +68,7 @@ class IntersectionTypeConstructor(typesToIntersect: Collection<KotlinType>) : Ty
KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
Annotations.EMPTY, this, listOf(), false, this.createScopeForKotlinType()
) { kotlinTypeRefiner ->
this.refine(kotlinTypeRefiner).createScopeForKotlinType()
this.refine(kotlinTypeRefiner).createType()
}
override fun hashCode(): Int = hashCode
@@ -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<TypeProjection>,
kotlinTypeRefiner: KotlinTypeRefiner? = null
): MemberScope {
val basicDescriptor = constructor.declarationDescriptor
val classId = basicDescriptor.safeAs<ClassifierDescriptorWithTypeParameters>()?.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<TypeProjection>,
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<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(
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<TypeProjection>,
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<TypeProjection>,
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
}
}
@@ -203,12 +203,21 @@ public class TypeUtils {
@NotNull
public static SimpleType makeUnsubstitutedType(
ClassifierDescriptor classifierDescriptor, MemberScope unsubstitutedMemberScope,
Function1<KotlinTypeRefiner, MemberScope> scopeFactory
Function1<KotlinTypeRefiner, SimpleType> 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<KotlinTypeRefiner, SimpleType> refinedTypeFactory
) {
List<TypeProjection> arguments = getDefaultTypeProjections(typeConstructor.getParameters());
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
Annotations.Companion.getEMPTY(),
@@ -216,7 +225,7 @@ public class TypeUtils {
arguments,
false,
unsubstitutedMemberScope,
scopeFactory
refinedTypeFactory
);
}