[Commonizer] Refactor CIR type representation

1. Drop CirClassifierId
2. Specialized classes for each kind of types (classes, TAs, type parameters, flexible types).
3. TypeCommonizer now returns commonized type. In case of TAs this could be a completely new type
   describing expect class or a new TA with the different underlying type.
This commit is contained in:
Dmitriy Dolovov
2020-10-19 20:33:23 +03:00
parent 2764550bbe
commit f5bb60f7cd
40 changed files with 818 additions and 340 deletions
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.descriptors.commonizer.builder
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.commonizer.cir.* import org.jetbrains.kotlin.descriptors.commonizer.cir.*
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.resolve.DescriptorFactory import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -101,31 +100,32 @@ internal fun CirSimpleType.buildType(
targetComponents: TargetDeclarationsBuilderComponents, targetComponents: TargetDeclarationsBuilderComponents,
typeParameterResolver: TypeParameterResolver, typeParameterResolver: TypeParameterResolver,
expandTypeAliases: Boolean expandTypeAliases: Boolean
): SimpleType { ): SimpleType = when (this) {
val classifier: ClassifierDescriptor = when (val classifierId = classifierId) { is CirClassType -> buildSimpleType(
is CirClassifierId.Class -> { classifier = targetComponents.findClassOrTypeAlias(classifierId).checkClassifierType<ClassDescriptor>(),
targetComponents.findClassOrTypeAlias(classifierId.classId).checkClassifierType<ClassDescriptor>() arguments = collectArguments(targetComponents, typeParameterResolver, expandTypeAliases),
} isMarkedNullable = isMarkedNullable
is CirClassifierId.TypeAlias -> { )
val classId = classifierId.classId is CirTypeAliasType -> {
val classOrTypeAlias: ClassifierDescriptorWithTypeParameters = targetComponents.findClassOrTypeAlias(classId) val typeAliasDescriptor = targetComponents.findClassOrTypeAlias(classifierId).checkClassifierType<TypeAliasDescriptor>()
val arguments = this.arguments.map { it.buildArgument(targetComponents, typeParameterResolver, expandTypeAliases) }
if (classId.packageFqName.isUnderStandardKotlinPackages || !targetComponents.isCommon) { if (expandTypeAliases)
// classifier type could be only type alias buildExpandedType(typeAliasDescriptor, arguments, isMarkedNullable)
classOrTypeAlias.checkClassifierType<TypeAliasDescriptor>() else
} else { buildSimpleType(typeAliasDescriptor, arguments, isMarkedNullable)
// classifier could be class or type alias
classOrTypeAlias
}
}
is CirClassifierId.TypeParameter -> {
typeParameterResolver.resolve(classifierId.index)
?: error("Type parameter $classifierId not found in ${typeParameterResolver::class.java}, $typeParameterResolver for ${targetComponents.target}")
}
} }
is CirTypeParameterType -> buildSimpleType(
classifier = typeParameterResolver.resolve(index)
?: error("Type parameter with index=$index not found in ${typeParameterResolver::class.java}, $typeParameterResolver for ${targetComponents.target}"),
arguments = emptyList(),
isMarkedNullable = isMarkedNullable
)
}
val arguments = arguments.map { it.buildArgument(targetComponents, typeParameterResolver, expandTypeAliases) } @Suppress("NOTHING_TO_INLINE")
val simpleType = simpleType( private inline fun buildSimpleType(classifier: ClassifierDescriptor, arguments: List<TypeProjection>, isMarkedNullable: Boolean) =
simpleType(
annotations = Annotations.EMPTY, annotations = Annotations.EMPTY,
constructor = classifier.typeConstructor, constructor = classifier.typeConstructor,
arguments = arguments, arguments = arguments,
@@ -133,29 +133,46 @@ internal fun CirSimpleType.buildType(
kotlinTypeRefiner = null kotlinTypeRefiner = null
) )
return if (expandTypeAliases && classifier is TypeAliasDescriptor) { @Suppress("NOTHING_TO_INLINE")
val expandedType = TypeAliasExpander.NON_REPORTING.expandWithoutAbbreviation( private inline fun buildExpandedType(classifier: TypeAliasDescriptor, arguments: List<TypeProjection>, isMarkedNullable: Boolean) =
TypeAliasExpander.NON_REPORTING.expand(
TypeAliasExpansion.create(null, classifier, arguments), TypeAliasExpansion.create(null, classifier, arguments),
Annotations.EMPTY Annotations.EMPTY
) ).makeNullableAsSpecified(isMarkedNullable)
expandedType.makeNullableAsSpecified(simpleType.isMarkedNullable).withAbbreviation(simpleType)
} else
simpleType
}
private inline fun <reified T : ClassifierDescriptorWithTypeParameters> ClassifierDescriptorWithTypeParameters.checkClassifierType(): T { private inline fun <reified T : ClassifierDescriptorWithTypeParameters> ClassifierDescriptorWithTypeParameters.checkClassifierType(): T {
check(this is T) { "Mismatched classifier kinds.\nFound: ${this::class.java}, $this\nShould be: ${T::class.java}" } check(this is T) { "Mismatched classifier kinds.\nFound: ${this::class.java}, $this\nShould be: ${T::class.java}" }
return this return this
} }
private fun CirClassType.collectArguments(
targetComponents: TargetDeclarationsBuilderComponents,
typeParameterResolver: TypeParameterResolver,
expandTypeAliases: Boolean
): List<TypeProjection> {
return if (outerType == null) {
arguments.map { it.buildArgument(targetComponents, typeParameterResolver, expandTypeAliases) }
} else {
val allTypes = generateSequence(this) { it.outerType }.toList()
val arguments = mutableListOf<TypeProjection>()
for (index in allTypes.size - 1 downTo 0) {
allTypes[index].arguments.mapTo(arguments) { it.buildArgument(targetComponents, typeParameterResolver, expandTypeAliases) }
}
arguments.toList()
}
}
private fun CirTypeProjection.buildArgument( private fun CirTypeProjection.buildArgument(
targetComponents: TargetDeclarationsBuilderComponents, targetComponents: TargetDeclarationsBuilderComponents,
typeParameterResolver: TypeParameterResolver, typeParameterResolver: TypeParameterResolver,
expandTypeAliases: Boolean expandTypeAliases: Boolean
): TypeProjection = ): TypeProjection = when (this) {
if (isStarProjection) { is CirStarTypeProjection -> StarProjectionForAbsentTypeParameter(targetComponents.builtIns)
StarProjectionForAbsentTypeParameter(targetComponents.builtIns) is CirTypeProjectionImpl -> TypeProjectionImpl(
} else { projectionKind,
TypeProjectionImpl(projectionKind, type.buildType(targetComponents, typeParameterResolver, expandTypeAliases)) type.buildType(targetComponents, typeParameterResolver, expandTypeAliases)
} )
}
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValue
interface CirAnnotation { interface CirAnnotation {
val type: CirSimpleType val type: CirClassType
val constantValueArguments: Map<Name, ConstantValue<*>> val constantValueArguments: Map<Name, ConstantValue<*>>
val annotationValueArguments: Map<Name, CirAnnotation> val annotationValueArguments: Map<Name, CirAnnotation>
} }
@@ -1,18 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.descriptors.commonizer.cir
import org.jetbrains.kotlin.name.ClassId
sealed class CirClassifierId {
interface ClassOrTypeAlias {
val classId: ClassId
}
data class Class(override val classId: ClassId) : ClassOrTypeAlias, CirClassifierId()
data class TypeAlias(override val classId: ClassId) : ClassOrTypeAlias, CirClassifierId()
data class TypeParameter(val index: Int) : CirClassifierId()
}
@@ -5,31 +5,107 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir package org.jetbrains.kotlin.descriptors.commonizer.cir
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.types.AbbreviatedType import org.jetbrains.kotlin.types.AbbreviatedType
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
typealias CirTypeSignature = String typealias CirTypeSignature = String
sealed class CirType /**
* The hierarchy of [CirType]:
*
* [CirType]
* / \
* [CirFlexibleType] [CirSimpleType]
* / \
* [CirTypeParameterType] [CirClassOrTypeAliasType]
* / \
* [CirClassType] [CirTypeAliasType]
*/
sealed class CirType {
final override fun toString() = buildString { appendDescriptionTo(this) }
internal abstract fun appendDescriptionTo(builder: StringBuilder)
}
data class CirFlexibleType(val lowerBound: CirSimpleType, val upperBound: CirSimpleType) : CirType() {
override fun appendDescriptionTo(builder: StringBuilder) {
builder.append("lower = ")
lowerBound.appendDescriptionTo(builder)
builder.append(", upper = ")
upperBound.appendDescriptionTo(builder)
}
}
/**
* Note: Annotations at simple types are not preserved. After commonization all annotations assigned to types will be lost.
*/
sealed class CirSimpleType : CirType() {
abstract val isMarkedNullable: Boolean
override fun appendDescriptionTo(builder: StringBuilder) {
if (isMarkedNullable) builder.append('?')
}
}
data class CirTypeParameterType(
val index: Int,
override val isMarkedNullable: Boolean
) : CirSimpleType() {
override fun appendDescriptionTo(builder: StringBuilder) {
builder.append('#').append(index)
super.appendDescriptionTo(builder)
}
}
sealed class CirClassOrTypeAliasType : CirSimpleType() {
abstract val classifierId: ClassId
abstract val arguments: List<CirTypeProjection>
override fun appendDescriptionTo(builder: StringBuilder) {
builder.append(classifierId.asString())
if (arguments.isNotEmpty()) arguments.joinTo(builder, prefix = "<", postfix = ">")
super.appendDescriptionTo(builder)
}
}
abstract class CirClassType : CirClassOrTypeAliasType(), CirHasVisibility {
abstract val outerType: CirClassType?
override fun appendDescriptionTo(builder: StringBuilder) {
outerType?.let {
it.appendDescriptionTo(builder)
builder.append('.')
}
super.appendDescriptionTo(builder)
}
}
/** /**
* All attributes are read from the abbreviation type: [AbbreviatedType.abbreviation]. * All attributes are read from the abbreviation type: [AbbreviatedType.abbreviation].
* *
* This is necessary to properly compare types for type aliases, where abbreviation type represents the type alias itself while * This is necessary to properly compare types for type aliases, where abbreviation type represents the type alias itself while
* expanded type represents right-hand side declaration that should be processed separately. * expanded type represents right-hand side declaration that should be processed separately.
*
* There is no difference between "abbreviation" and "expanded" for types representing classes and type parameters.
* For details, see [CirTypeFactory].
*
* Note: Annotations at simple types are not preserved. After commonization all annotations assigned to types will be lost.
*/ */
abstract class CirSimpleType : CirType(), CirHasVisibility { abstract class CirTypeAliasType : CirClassOrTypeAliasType() {
abstract val classifierId: CirClassifierId abstract val underlyingType: CirClassOrTypeAliasType
abstract val arguments: List<CirTypeProjection>
abstract val isMarkedNullable: Boolean override fun appendDescriptionTo(builder: StringBuilder) {
super.appendDescriptionTo(builder)
builder.append(" -> ")
underlyingType.appendDescriptionTo(builder)
}
} }
data class CirFlexibleType(val lowerBound: CirSimpleType, val upperBound: CirSimpleType) : CirType() sealed class CirTypeProjection
data class CirTypeProjection(val projectionKind: Variance, val isStarProjection: Boolean, val type: CirType) object CirStarTypeProjection : CirTypeProjection() {
override fun toString() = "*"
}
data class CirTypeProjectionImpl(val projectionKind: Variance, val type: CirType) : CirTypeProjection() {
override fun toString() = buildString {
append(projectionKind)
if (isNotEmpty()) append(' ')
type.appendDescriptionTo(this)
}
}
@@ -6,6 +6,6 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir package org.jetbrains.kotlin.descriptors.commonizer.cir
interface CirTypeAlias : CirClassifier, CirLiftedUpDeclaration { interface CirTypeAlias : CirClassifier, CirLiftedUpDeclaration {
val underlyingType: CirSimpleType val underlyingType: CirClassOrTypeAliasType
val expandedType: CirSimpleType val expandedType: CirClassType
} }
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
import gnu.trove.THashMap import gnu.trove.THashMap
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassType
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirAnnotationImpl import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirAnnotationImpl
import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner
import org.jetbrains.kotlin.descriptors.commonizer.utils.checkConstantSupportedInCommonization import org.jetbrains.kotlin.descriptors.commonizer.utils.checkConstantSupportedInCommonization
@@ -21,7 +21,7 @@ object CirAnnotationFactory {
private val interner = Interner<CirAnnotation>() private val interner = Interner<CirAnnotation>()
fun create(source: AnnotationDescriptor): CirAnnotation { fun create(source: AnnotationDescriptor): CirAnnotation {
val type = CirTypeFactory.create(source.type) as CirSimpleType val type = CirTypeFactory.create(source.type, useAbbreviation = false) as CirClassType
val allValueArguments: Map<Name, ConstantValue<*>> = source.allValueArguments val allValueArguments: Map<Name, ConstantValue<*>> = source.allValueArguments
if (allValueArguments.isEmpty()) if (allValueArguments.isEmpty())
@@ -52,7 +52,7 @@ object CirAnnotationFactory {
} }
fun create( fun create(
type: CirSimpleType, type: CirClassType,
constantValueArguments: Map<Name, ConstantValue<*>>, constantValueArguments: Map<Name, ConstantValue<*>>,
annotationValueArguments: Map<Name, CirAnnotation> annotationValueArguments: Map<Name, CirAnnotation>
): CirAnnotation { ): CirAnnotation {
@@ -1,38 +0,0 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifierId
import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner
import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId
import org.jetbrains.kotlin.name.ClassId
@Suppress("MemberVisibilityCanBePrivate")
object CirClassifierIdFactory {
private val interner = Interner<CirClassifierId>()
fun create(source: ClassifierDescriptor): CirClassifierId {
return when (source) {
is ClassDescriptor -> createForClass(source.internedClassId)
is TypeAliasDescriptor -> createForTypeAlias(source.internedClassId)
is TypeParameterDescriptor -> createForTypeParameter(source.typeParameterIndex)
else -> error("Unexpected classifier descriptor type: ${source::class.java}, $this")
}
}
fun createForClass(classId: ClassId): CirClassifierId = interner.intern(CirClassifierId.Class(classId))
fun createForTypeAlias(classId: ClassId): CirClassifierId = interner.intern(CirClassifierId.TypeAlias(classId))
fun createForTypeParameter(index: Int): CirClassifierId = interner.intern(CirClassifierId.TypeParameter(index))
}
private inline val TypeParameterDescriptor.typeParameterIndex: Int
get() {
var index = index
var parent = containingDeclaration
while ((parent as? ClassifierDescriptorWithTypeParameters)?.isInner != false) {
parent = parent.containingDeclaration as? ClassifierDescriptorWithTypeParameters ?: break
index += parent.declaredTypeParameters.size
}
return index
}
@@ -7,10 +7,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation import org.jetbrains.kotlin.descriptors.commonizer.cir.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeAlias
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirTypeAliasImpl import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirTypeAliasImpl
import org.jetbrains.kotlin.descriptors.commonizer.utils.intern import org.jetbrains.kotlin.descriptors.commonizer.utils.intern
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -21,8 +18,8 @@ object CirTypeAliasFactory {
name = source.name.intern(), name = source.name.intern(),
typeParameters = source.declaredTypeParameters.map(CirTypeParameterFactory::create), typeParameters = source.declaredTypeParameters.map(CirTypeParameterFactory::create),
visibility = source.visibility, visibility = source.visibility,
underlyingType = CirTypeFactory.create(source.underlyingType), underlyingType = CirTypeFactory.create(source.underlyingType, useAbbreviation = true) as CirClassOrTypeAliasType,
expandedType = CirTypeFactory.create(source.expandedType, useAbbreviation = false) expandedType = CirTypeFactory.create(source.expandedType, useAbbreviation = false) as CirClassType
) )
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
@@ -31,8 +28,8 @@ object CirTypeAliasFactory {
name: Name, name: Name,
typeParameters: List<CirTypeParameter>, typeParameters: List<CirTypeParameter>,
visibility: DescriptorVisibility, visibility: DescriptorVisibility,
underlyingType: CirSimpleType, underlyingType: CirClassOrTypeAliasType,
expandedType: CirSimpleType expandedType: CirClassType
): CirTypeAlias { ): CirTypeAlias {
return CirTypeAliasImpl( return CirTypeAliasImpl(
annotations = annotations, annotations = annotations,
@@ -5,58 +5,168 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir.factory package org.jetbrains.kotlin.descriptors.commonizer.cir.factory
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.commonizer.cir.* import org.jetbrains.kotlin.descriptors.commonizer.cir.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirSimpleTypeImpl import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirClassTypeImpl
import org.jetbrains.kotlin.descriptors.commonizer.cir.impl.CirTypeAliasTypeImpl
import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner import org.jetbrains.kotlin.descriptors.commonizer.utils.Interner
import org.jetbrains.kotlin.descriptors.commonizer.utils.declarationDescriptor import org.jetbrains.kotlin.descriptors.commonizer.utils.declarationDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.utils.extractExpandedType
import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
object CirTypeFactory { object CirTypeFactory {
private val interner = Interner<CirSimpleType>() private val classTypeInterner = Interner<CirClassType>()
private val typeAliasTypeInterner = Interner<CirTypeAliasType>()
private val typeParameterTypeInterner = Interner<CirTypeParameterType>()
fun create(source: KotlinType): CirType = source.unwrap().run { fun create(source: KotlinType, useAbbreviation: Boolean = true): CirType = source.unwrap().run {
when (this) { when (this) {
is SimpleType -> create(this) is SimpleType -> create(this, useAbbreviation)
is FlexibleType -> CirFlexibleType(create(lowerBound), create(upperBound)) is FlexibleType -> CirFlexibleType(create(lowerBound, useAbbreviation), create(upperBound, useAbbreviation))
} }
} }
fun create(source: SimpleType, useAbbreviation: Boolean = true): CirSimpleType { fun create(source: SimpleType, useAbbreviation: Boolean): CirSimpleType {
@Suppress("NAME_SHADOWING") if (useAbbreviation && source is AbbreviatedType) {
val source = if (useAbbreviation && source is AbbreviatedType) source.abbreviation else source val abbreviation = source.abbreviation
val classifierDescriptor: ClassifierDescriptor = source.declarationDescriptor when (val classifierDescriptor = abbreviation.declarationDescriptor) {
is TypeAliasDescriptor -> {
return create( return createTypeAliasType(
classifierId = CirClassifierIdFactory.create(classifierDescriptor), typeAliasId = classifierDescriptor.internedClassId,
visibility = (classifierDescriptor as? ClassifierDescriptorWithTypeParameters)?.visibility ?: DescriptorVisibilities.UNKNOWN, underlyingType = create(extractExpandedType(source), useAbbreviation = true) as CirClassOrTypeAliasType,
arguments = source.arguments.map { projection -> arguments = createArguments(abbreviation.arguments, useAbbreviation = true),
CirTypeProjection( isMarkedNullable = abbreviation.isMarkedNullable
projectionKind = projection.projectionKind,
isStarProjection = projection.isStarProjection,
type = create(projection.type)
) )
}, }
else -> error("Unexpected classifier descriptor type for abbreviation type: ${classifierDescriptor::class.java}, $classifierDescriptor, ${source.abbreviation}")
}
}
return when (val classifierDescriptor = source.declarationDescriptor) {
is ClassDescriptor -> createClassTypeWithAllOuterTypes(
classDescriptor = classifierDescriptor,
arguments = createArguments(source.arguments, useAbbreviation),
isMarkedNullable = source.isMarkedNullable
)
is TypeAliasDescriptor -> {
val abbreviatedType = TypeAliasExpander.NON_REPORTING.expand(
TypeAliasExpansion.create(null, classifierDescriptor, source.arguments),
Annotations.EMPTY
) as AbbreviatedType
createTypeAliasType(
typeAliasId = classifierDescriptor.internedClassId,
underlyingType = create(extractExpandedType(abbreviatedType), useAbbreviation = true) as CirClassOrTypeAliasType,
arguments = createArguments(source.arguments, useAbbreviation = true),
isMarkedNullable = source.isMarkedNullable isMarkedNullable = source.isMarkedNullable
) )
} }
is TypeParameterDescriptor -> createTypeParameterType(classifierDescriptor.typeParameterIndex, source.isMarkedNullable)
else -> error("Unexpected classifier descriptor type: ${classifierDescriptor::class.java}, $classifierDescriptor, $source")
}
}
fun create( fun createClassType(
classifierId: CirClassifierId, classId: ClassId,
outerType: CirClassType?,
visibility: DescriptorVisibility, visibility: DescriptorVisibility,
arguments: List<CirTypeProjection>, arguments: List<CirTypeProjection>,
isMarkedNullable: Boolean isMarkedNullable: Boolean
): CirSimpleType { ): CirClassType {
return interner.intern( return classTypeInterner.intern(
CirSimpleTypeImpl( CirClassTypeImpl(
classifierId = classifierId, classifierId = classId,
outerType = outerType,
visibility = visibility, visibility = visibility,
arguments = arguments, arguments = arguments,
isMarkedNullable = isMarkedNullable isMarkedNullable = isMarkedNullable
) )
) )
} }
fun createTypeAliasType(
typeAliasId: ClassId,
underlyingType: CirClassOrTypeAliasType,
arguments: List<CirTypeProjection>,
isMarkedNullable: Boolean
): CirTypeAliasType {
return typeAliasTypeInterner.intern(
CirTypeAliasTypeImpl(
classifierId = typeAliasId,
underlyingType = underlyingType,
arguments = arguments,
isMarkedNullable = isMarkedNullable
)
)
}
fun createTypeParameterType(
index: Int,
isMarkedNullable: Boolean
): CirTypeParameterType {
return typeParameterTypeInterner.intern(
CirTypeParameterType(
index = index,
isMarkedNullable = isMarkedNullable
)
)
}
private fun createClassTypeWithAllOuterTypes(
classDescriptor: ClassDescriptor,
arguments: List<CirTypeProjection>,
isMarkedNullable: Boolean
): CirClassType {
val outerType: CirClassType?
val remainingArguments: List<CirTypeProjection>
if (classDescriptor.isInner) {
val declaredTypeParametersCount = classDescriptor.declaredTypeParameters.size
outerType = createClassTypeWithAllOuterTypes(
classDescriptor = classDescriptor.containingDeclaration as ClassDescriptor,
arguments = arguments.subList(0, arguments.size - declaredTypeParametersCount),
isMarkedNullable = false // don't pass nullable flag to outer types
)
remainingArguments = arguments.subList(arguments.size - declaredTypeParametersCount, arguments.size)
} else {
outerType = null
remainingArguments = arguments
}
return createClassType(
classId = classDescriptor.internedClassId,
outerType = outerType,
visibility = classDescriptor.visibility,
arguments = remainingArguments,
isMarkedNullable = isMarkedNullable
)
}
@Suppress("NOTHING_TO_INLINE")
private inline fun createArguments(arguments: List<TypeProjection>, useAbbreviation: Boolean): List<CirTypeProjection> =
arguments.map { projection ->
if (projection.isStarProjection)
CirStarTypeProjection
else
CirTypeProjectionImpl(
projectionKind = projection.projectionKind,
type = create(projection.type, useAbbreviation)
)
}
private inline val TypeParameterDescriptor.typeParameterIndex: Int
get() {
var index = index
var parent = containingDeclaration
while ((parent as? ClassifierDescriptorWithTypeParameters)?.isInner != false) {
parent = parent.containingDeclaration as? ClassifierDescriptorWithTypeParameters ?: break
index += parent.declaredTypeParameters.size
}
return index
}
} }
@@ -6,14 +6,14 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir.impl package org.jetbrains.kotlin.descriptors.commonizer.cir.impl
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassType
import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode
import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.ConstantValue
data class CirAnnotationImpl( data class CirAnnotationImpl(
override val type: CirSimpleType, override val type: CirClassType,
override val constantValueArguments: Map<Name, ConstantValue<*>>, override val constantValueArguments: Map<Name, ConstantValue<*>>,
override val annotationValueArguments: Map<Name, CirAnnotation> override val annotationValueArguments: Map<Name, CirAnnotation>
) : CirAnnotation { ) : CirAnnotation {
@@ -6,20 +6,24 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir.impl package org.jetbrains.kotlin.descriptors.commonizer.cir.impl
import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.commonizer.cir.* import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassType
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeProjection
import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode
import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode
import org.jetbrains.kotlin.name.ClassId
data class CirSimpleTypeImpl( data class CirClassTypeImpl(
override val classifierId: CirClassifierId, override val classifierId: ClassId,
override val visibility: DescriptorVisibility, // visibility of the classifier descriptor override val outerType: CirClassType?,
override val visibility: DescriptorVisibility, // visibility of the class descriptor
override val arguments: List<CirTypeProjection>, override val arguments: List<CirTypeProjection>,
override val isMarkedNullable: Boolean override val isMarkedNullable: Boolean,
) : CirSimpleType() { ) : CirClassType() {
// See also org.jetbrains.kotlin.types.KotlinType.cachedHashCode // See also org.jetbrains.kotlin.types.KotlinType.cachedHashCode
private var cachedHashCode = 0 private var cachedHashCode = 0
private fun computeHashCode() = hashCode(classifierId) private fun computeHashCode() = hashCode(classifierId)
.appendHashCode(outerType)
.appendHashCode(visibility) .appendHashCode(visibility)
.appendHashCode(arguments) .appendHashCode(arguments)
.appendHashCode(isMarkedNullable) .appendHashCode(isMarkedNullable)
@@ -33,13 +37,14 @@ data class CirSimpleTypeImpl(
return currentHashCode return currentHashCode
} }
override fun equals(other: Any?) = when { override fun equals(other: Any?): Boolean = when {
other === this -> true other === this -> true
other is CirSimpleType -> { other is CirClassType -> {
isMarkedNullable == other.isMarkedNullable classifierId == other.classifierId
&& classifierId == other.classifierId && isMarkedNullable == other.isMarkedNullable
&& visibility == other.visibility && visibility == other.visibility
&& arguments == other.arguments && arguments == other.arguments
&& outerType == other.outerType
} }
else -> false else -> false
} }
@@ -6,10 +6,7 @@
package org.jetbrains.kotlin.descriptors.commonizer.cir.impl package org.jetbrains.kotlin.descriptors.commonizer.cir.impl
import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation import org.jetbrains.kotlin.descriptors.commonizer.cir.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeAlias
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeParameter
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
data class CirTypeAliasImpl( data class CirTypeAliasImpl(
@@ -17,8 +14,8 @@ data class CirTypeAliasImpl(
override val name: Name, override val name: Name,
override val typeParameters: List<CirTypeParameter>, override val typeParameters: List<CirTypeParameter>,
override val visibility: DescriptorVisibility, override val visibility: DescriptorVisibility,
override val underlyingType: CirSimpleType, override val underlyingType: CirClassOrTypeAliasType,
override val expandedType: CirSimpleType // only for commonization algorithm; does not participate in building resulting declarations override val expandedType: CirClassType // only for commonization algorithm; does not participate in building resulting declarations
) : CirTypeAlias { ) : CirTypeAlias {
// any TA in "common" fragment is already lifted up // any TA in "common" fragment is already lifted up
override val isLiftedUp get() = true override val isLiftedUp get() = true
@@ -0,0 +1,48 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.descriptors.commonizer.cir.impl
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassOrTypeAliasType
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeAliasType
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeProjection
import org.jetbrains.kotlin.descriptors.commonizer.utils.appendHashCode
import org.jetbrains.kotlin.descriptors.commonizer.utils.hashCode
import org.jetbrains.kotlin.name.ClassId
data class CirTypeAliasTypeImpl(
override val classifierId: ClassId,
override val underlyingType: CirClassOrTypeAliasType,
override val arguments: List<CirTypeProjection>,
override val isMarkedNullable: Boolean
) : CirTypeAliasType() {
// See also org.jetbrains.kotlin.types.KotlinType.cachedHashCode
private var cachedHashCode = 0
private fun computeHashCode() = hashCode(classifierId)
.appendHashCode(underlyingType)
.appendHashCode(arguments)
.appendHashCode(isMarkedNullable)
override fun hashCode(): Int {
var currentHashCode = cachedHashCode
if (currentHashCode != 0) return currentHashCode
currentHashCode = computeHashCode()
cachedHashCode = currentHashCode
return currentHashCode
}
override fun equals(other: Any?): Boolean = when {
other === this -> true
other is CirTypeAliasType -> {
classifierId == other.classifierId
&& underlyingType == other.underlyingType
&& isMarkedNullable == other.isMarkedNullable
&& arguments == other.arguments
}
else -> false
}
}
@@ -7,9 +7,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifierId
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirAnnotationFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirAnnotationFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassifierIdFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory
import org.jetbrains.kotlin.descriptors.commonizer.core.AnnotationsCommonizer.Companion.FALLBACK_MESSAGE import org.jetbrains.kotlin.descriptors.commonizer.core.AnnotationsCommonizer.Companion.FALLBACK_MESSAGE
import org.jetbrains.kotlin.descriptors.commonizer.utils.DEPRECATED_ANNOTATION_CID import org.jetbrains.kotlin.descriptors.commonizer.utils.DEPRECATED_ANNOTATION_CID
@@ -38,9 +36,7 @@ class AnnotationsCommonizer : AbstractStandardCommonizer<List<CirAnnotation>, Li
override fun initialize(first: List<CirAnnotation>) = Unit override fun initialize(first: List<CirAnnotation>) = Unit
override fun doCommonizeWith(next: List<CirAnnotation>): Boolean { override fun doCommonizeWith(next: List<CirAnnotation>): Boolean {
val nextDeprecatedAnnotation = next.firstOrNull { annotation -> val nextDeprecatedAnnotation = next.firstOrNull { it.type.classifierId == DEPRECATED_ANNOTATION_CID } ?: return true
(annotation.type.classifierId as? CirClassifierId.Class)?.classId == DEPRECATED_ANNOTATION_CID
} ?: return true
val deprecatedAnnotationCommonizer = deprecatedAnnotationCommonizer val deprecatedAnnotationCommonizer = deprecatedAnnotationCommonizer
?: DeprecatedAnnotationCommonizer().also { this.deprecatedAnnotationCommonizer = it } ?: DeprecatedAnnotationCommonizer().also { this.deprecatedAnnotationCommonizer = it }
@@ -160,8 +156,9 @@ private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnno
it.name to EnumValue(DEPRECATION_LEVEL_CID, Name.identifier(it.name).intern()) it.name to EnumValue(DEPRECATION_LEVEL_CID, Name.identifier(it.name).intern())
} }
private fun buildAnnotationType(classId: ClassId) = CirTypeFactory.create( private fun buildAnnotationType(classId: ClassId) = CirTypeFactory.createClassType(
classifierId = CirClassifierIdFactory.createForClass(classId), classId = classId,
outerType = null,
visibility = DescriptorVisibilities.PUBLIC, visibility = DescriptorVisibilities.PUBLIC,
arguments = emptyList(), arguments = emptyList(),
isMarkedNullable = false isMarkedNullable = false
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
import com.intellij.util.containers.FactoryMap import com.intellij.util.containers.FactoryMap
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirCallableMemberWithParameters import org.jetbrains.kotlin.descriptors.commonizer.cir.CirCallableMemberWithParameters
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifierId
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirHasAnnotations import org.jetbrains.kotlin.descriptors.commonizer.cir.CirHasAnnotations
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirValueParameter import org.jetbrains.kotlin.descriptors.commonizer.cir.CirValueParameter
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirValueParameterFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirValueParameterFactory
@@ -229,9 +228,7 @@ class CallableValueParametersCommonizer(
} }
private fun CirCallableMemberWithParameters.canNamesBeOverwritten(): Boolean { private fun CirCallableMemberWithParameters.canNamesBeOverwritten(): Boolean {
return (this as CirHasAnnotations).annotations.none { annotation -> return (this as CirHasAnnotations).annotations.none { it.type.classifierId.isObjCInteropCallableAnnotation }
(annotation.type.classifierId as? CirClassifierId.ClassOrTypeAlias)?.classId?.isObjCInteropCallableAnnotation == true
}
} }
private fun failIllegalState(current: ValueParameterNames?, next: ValueParameterNames): Nothing = private fun failIllegalState(current: ValueParameterNames?, next: ValueParameterNames): Nothing =
@@ -6,13 +6,11 @@
package org.jetbrains.kotlin.descriptors.commonizer.core package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifierId
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.* import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.*
import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup
import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId import org.jetbrains.kotlin.descriptors.commonizer.utils.internedClassId
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages
import org.jetbrains.kotlin.utils.addToStdlib.cast
internal class CommonizationVisitor( internal class CommonizationVisitor(
private val root: CirRootNode private val root: CirRootNode
@@ -128,7 +126,7 @@ internal class CommonizationVisitor(
private fun CirTypeAliasNode.collectCommonSupertypes(): Map<CirType, CommonizedGroup<CirType>>? { private fun CirTypeAliasNode.collectCommonSupertypes(): Map<CirType, CommonizedGroup<CirType>>? {
val supertypesMap: MutableMap<CirType, CommonizedGroup<CirType>> = linkedMapOf() // preserve supertype order val supertypesMap: MutableMap<CirType, CommonizedGroup<CirType>> = linkedMapOf() // preserve supertype order
for ((index, typeAlias) in targetDeclarations.withIndex()) { for ((index, typeAlias) in targetDeclarations.withIndex()) {
val expandedClassId = typeAlias!!.expandedType.classifierId.cast<CirClassifierId.Class>().classId val expandedClassId = typeAlias!!.expandedType.classifierId
if (expandedClassId.packageFqName.isUnderStandardKotlinPackages) if (expandedClassId.packageFqName.isUnderStandardKotlinPackages)
return null // this case is not supported return null // this case is not supported
@@ -56,7 +56,7 @@ fun Commonizer<*, *>.failInEmptyState(): Nothing = throw IllegalCommonizerStateE
@Suppress("unused") @Suppress("unused")
fun Commonizer<*, *>.failInErrorState(): Nothing = throw IllegalCommonizerStateException("empty") fun Commonizer<*, *>.failInErrorState(): Nothing = throw IllegalCommonizerStateException("empty")
fun <T : Any> Commonizer<*, *>.checkState(value: T?, error: Boolean): T = when { inline fun <reified T : Any> Commonizer<*, *>.checkState(value: T?, error: Boolean): T = when {
value == null -> failInEmptyState() value == null -> failInEmptyState()
error -> failInErrorState() error -> failInErrorState()
else -> value else -> value
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeAliasFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeAliasFactory
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
/** /**
@@ -32,7 +33,6 @@ class TypeAliasCommonizer(cache: CirClassifiersCache) : AbstractStandardCommoniz
override fun initialize(first: CirTypeAlias) = Unit override fun initialize(first: CirTypeAlias) = Unit
@Suppress("ReplaceNegatedIsEmptyWithIsNotEmpty")
override fun doCommonizeWith(next: CirTypeAlias): Boolean { override fun doCommonizeWith(next: CirTypeAlias): Boolean {
val primaryResult = primary.commonizeWith(next) val primaryResult = primary.commonizeWith(next)
val secondaryResult = secondary.commonizeWith(next) val secondaryResult = secondary.commonizeWith(next)
@@ -46,63 +46,80 @@ class TypeAliasCommonizer(cache: CirClassifiersCache) : AbstractStandardCommoniz
private class TypeAliasShortCircuitingCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirTypeAlias, CirTypeAlias>() { private class TypeAliasShortCircuitingCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirTypeAlias, CirTypeAlias>() {
private lateinit var name: Name private lateinit var name: Name
private val typeParameters = TypeParameterListCommonizer(cache) private val typeParameters = TypeParameterListCommonizer(cache)
private lateinit var underlyingType: CirClassOrTypeAliasType
private val expandedType = TypeCommonizer(cache) private val expandedType = TypeCommonizer(cache)
private val visibility = VisibilityCommonizer.lowering() private val visibility = VisibilityCommonizer.lowering()
override fun commonizationResult(): CirTypeAlias { override fun commonizationResult() = CirTypeAliasFactory.create(
val expandedType = expandedType.result as CirSimpleType
return CirTypeAliasFactory.create(
annotations = emptyList(), annotations = emptyList(),
name = name, name = name,
typeParameters = typeParameters.result, typeParameters = typeParameters.result,
visibility = visibility.result, visibility = visibility.result,
underlyingType = expandedType, // pass expanded type as underlying type underlyingType = computeCommonizedUnderlyingType(underlyingType),
expandedType = expandedType expandedType = expandedType.result as CirClassType
) )
}
val resultOrNull: CirTypeAlias? val resultOrNull: CirTypeAlias?
get() = if (hasResult) commonizationResult() else null get() = if (hasResult) commonizationResult() else null
override fun initialize(first: CirTypeAlias) { override fun initialize(first: CirTypeAlias) {
name = first.name name = first.name
underlyingType = first.underlyingType
} }
override fun doCommonizeWith(next: CirTypeAlias) = override fun doCommonizeWith(next: CirTypeAlias) =
typeParameters.commonizeWith(next.typeParameters) typeParameters.commonizeWith(next.typeParameters)
&& expandedType.commonizeWith(next.expandedType) && expandedType.commonizeWith(next.expandedType)
&& visibility.commonizeWith(next) && visibility.commonizeWith(next)
private tailrec fun computeCommonizedUnderlyingType(underlyingType: CirClassOrTypeAliasType): CirClassOrTypeAliasType {
return when (underlyingType) {
is CirClassType -> underlyingType
is CirTypeAliasType -> if (underlyingType.classifierId.packageFqName.isUnderStandardKotlinPackages)
underlyingType
else
computeCommonizedUnderlyingType(underlyingType.underlyingType)
}
}
} }
private class TypeAliasLiftingUpCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirTypeAlias, CirTypeAlias>() { private class TypeAliasLiftingUpCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirTypeAlias, CirTypeAlias>() {
private lateinit var name: Name private lateinit var name: Name
private val typeParameters = TypeParameterListCommonizer(cache) private val typeParameters = TypeParameterListCommonizer(cache)
private val underlyingType = TypeCommonizer(cache) private val underlyingType = TypeCommonizer(cache)
private lateinit var expandedType: CirSimpleType
private val visibility = VisibilityCommonizer.lowering() private val visibility = VisibilityCommonizer.lowering()
override fun commonizationResult(): CirTypeAlias = CirTypeAliasFactory.create( override fun commonizationResult(): CirTypeAlias {
val underlyingType = underlyingType.result as CirClassOrTypeAliasType
return CirTypeAliasFactory.create(
annotations = emptyList(), annotations = emptyList(),
name = name, name = name,
typeParameters = typeParameters.result, typeParameters = typeParameters.result,
visibility = visibility.result, visibility = visibility.result,
underlyingType = underlyingType.result as CirSimpleType, underlyingType = underlyingType,
expandedType = expandedType expandedType = computeCommonizedExpandedType(underlyingType)
) )
}
val resultOrNull: CirTypeAlias? val resultOrNull: CirTypeAlias?
get() = if (hasResult) commonizationResult() else null get() = if (hasResult) commonizationResult() else null
override fun initialize(first: CirTypeAlias) { override fun initialize(first: CirTypeAlias) {
name = first.name name = first.name
expandedType = first.expandedType
} }
override fun doCommonizeWith(next: CirTypeAlias) = override fun doCommonizeWith(next: CirTypeAlias) =
typeParameters.commonizeWith(next.typeParameters) typeParameters.commonizeWith(next.typeParameters)
&& underlyingType.commonizeWith(next.underlyingType) && underlyingType.commonizeWith(next.underlyingType)
&& visibility.commonizeWith(next) && visibility.commonizeWith(next)
private tailrec fun computeCommonizedExpandedType(underlyingType: CirClassOrTypeAliasType): CirClassType {
return when (underlyingType) {
is CirClassType -> underlyingType
is CirTypeAliasType -> computeCommonizedExpandedType(underlyingType.underlyingType)
}
}
} }
private class TypeAliasExpectClassCommonizer : AbstractStandardCommonizer<CirTypeAlias, CirClass>() { private class TypeAliasExpectClassCommonizer : AbstractStandardCommonizer<CirTypeAlias, CirClass>() {
@@ -129,9 +146,19 @@ private class TypeAliasExpectClassCommonizer : AbstractStandardCommonizer<CirTyp
name = first.name name = first.name
} }
override fun doCommonizeWith(next: CirTypeAlias) = override fun doCommonizeWith(next: CirTypeAlias): Boolean {
next.typeParameters.isEmpty() // TAs with declared type parameters can't be commonized if (next.typeParameters.isNotEmpty())
&& next.underlyingType.arguments.isEmpty() // TAs with functional types or types with parameters at the right-hand side can't be commonized return false // TAs with declared type parameters can't be commonized
&& next.underlyingType.classifierId is CirClassifierId.Class // right-hand side could have only class
&& classVisibility.commonizeWith(next.underlyingType) // the visibilities of the right-hand classes should be equal val underlyingType = next.underlyingType as? CirClassType ?: return false // right-hand side could have only class
return hasNoArguments(underlyingType) // TAs with functional types or types with arguments at the right-hand side can't be commonized
&& classVisibility.commonizeWith(underlyingType) // the visibilities of the right-hand classes should be equal
}
private tailrec fun hasNoArguments(type: CirClassType?): Boolean =
when {
type == null -> true
type.arguments.isNotEmpty() -> false
else -> hasNoArguments(type.outerType)
}
} }
@@ -5,105 +5,231 @@
package org.jetbrains.kotlin.descriptors.commonizer.core package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.commonizer.cir.* import org.jetbrains.kotlin.descriptors.commonizer.cir.*
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderStandardKotlinPackages
import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.types.Variance
class TypeCommonizer(private val cache: CirClassifiersCache) : AbstractStandardCommonizer<CirType, CirType>() { class TypeCommonizer(private val cache: CirClassifiersCache) : AbstractStandardCommonizer<CirType, CirType>() {
private lateinit var temp: CirType private lateinit var wrapped: Commonizer<*, CirType>
override fun commonizationResult() = wrapped.result
override fun initialize(first: CirType) {
@Suppress("UNCHECKED_CAST")
wrapped = when (first) {
is CirClassType -> ClassTypeCommonizer(cache)
is CirTypeAliasType -> TypeAliasTypeCommonizer(cache)
is CirTypeParameterType -> TypeParameterTypeCommonizer()
is CirFlexibleType -> FlexibleTypeCommonizer(cache)
} as Commonizer<*, CirType>
}
override fun doCommonizeWith(next: CirType) = when (next) {
is CirClassType -> (wrapped as? ClassTypeCommonizer)?.commonizeWith(next) == true
is CirTypeAliasType -> (wrapped as? TypeAliasTypeCommonizer)?.commonizeWith(next) == true
is CirTypeParameterType -> (wrapped as? TypeParameterTypeCommonizer)?.commonizeWith(next) == true
is CirFlexibleType -> (wrapped as? FlexibleTypeCommonizer)?.commonizeWith(next) == true
}
}
private class ClassTypeCommonizer(private val cache: CirClassifiersCache) : AbstractStandardCommonizer<CirClassType, CirClassType>() {
private lateinit var classId: ClassId
private val outerType = OuterClassTypeCommonizer(cache)
private lateinit var anyVisibility: DescriptorVisibility
private val arguments = TypeArgumentListCommonizer(cache)
private var isMarkedNullable = false
override fun commonizationResult() = CirTypeFactory.createClassType(
classId = classId,
outerType = outerType.result,
// N.B. The 'visibility' field in class types is needed ONLY for TA commonization. The class type constructed here is
// intended to be used in "common" target. It could not participate in TA commonization. So, it does not matter which
// exactly visibility will be recorded for commonized class type. Passing the visibility of the first class type
// to reach better interning rate.
visibility = anyVisibility,
arguments = arguments.result,
isMarkedNullable = isMarkedNullable
)
override fun initialize(first: CirClassType) {
classId = first.classifierId
anyVisibility = first.visibility
isMarkedNullable = first.isMarkedNullable
}
override fun doCommonizeWith(next: CirClassType) =
isMarkedNullable == next.isMarkedNullable
&& classId == next.classifierId
&& outerType.commonizeWith(next.outerType)
&& commonizeClassifier(classId, cache.classes).first
&& arguments.commonizeWith(next.arguments)
}
private class OuterClassTypeCommonizer(cache: CirClassifiersCache) :
AbstractNullableCommonizer<CirClassType, CirClassType, CirClassType, CirClassType>(
wrappedCommonizerFactory = { ClassTypeCommonizer(cache) },
extractor = { it },
builder = { it }
)
private class TypeAliasTypeCommonizer(private val cache: CirClassifiersCache) :
AbstractStandardCommonizer<CirTypeAliasType, CirClassOrTypeAliasType>() {
private lateinit var typeAliasId: ClassId
private val arguments = TypeArgumentListCommonizer(cache)
private var isMarkedNullable = false
private var commonizedTypeBuilder: CommonizedTypeAliasTypeBuilder? = null // null means not selected yet
override fun commonizationResult() =
(commonizedTypeBuilder ?: failInEmptyState()).build(
typeAliasId = typeAliasId,
arguments = arguments.result,
isMarkedNullable = isMarkedNullable
)
override fun initialize(first: CirTypeAliasType) {
typeAliasId = first.classifierId
isMarkedNullable = first.isMarkedNullable
}
override fun doCommonizeWith(next: CirTypeAliasType): Boolean {
if (isMarkedNullable != next.isMarkedNullable || typeAliasId != next.classifierId)
return false
if (commonizedTypeBuilder == null) {
val (commonized, commonClassifier) = commonizeClassifier(typeAliasId, cache.typeAliases)
if (!commonized)
return false
commonizedTypeBuilder = when (commonClassifier) {
is CirClass -> CommonizedTypeAliasTypeBuilder.forClass(commonClassifier)
is CirTypeAlias -> CommonizedTypeAliasTypeBuilder.forTypeAlias(commonClassifier)
null -> CommonizedTypeAliasTypeBuilder.forKnownUnderlyingType(next.underlyingType)
else -> error("Unexpected common classifier type: ${commonClassifier::class.java}, $commonClassifier")
}
}
return arguments.commonizeWith(next.arguments)
}
// builds a new type for "common" library fragment for the given combination of type alias types in "platform" fragments
private interface CommonizedTypeAliasTypeBuilder {
fun build(typeAliasId: ClassId, arguments: List<CirTypeProjection>, isMarkedNullable: Boolean): CirClassOrTypeAliasType
companion object {
// type alias has been commonized to expect class, need to build type for expect class
fun forClass(commonClass: CirClass) = object : CommonizedTypeAliasTypeBuilder {
override fun build(typeAliasId: ClassId, arguments: List<CirTypeProjection>, isMarkedNullable: Boolean) =
CirTypeFactory.createClassType(
classId = typeAliasId,
outerType = null, // there can't be outer type
visibility = commonClass.visibility,
arguments = arguments,
isMarkedNullable = isMarkedNullable
)
}
// type alias has been commonized to another type alias with the different underlying type, need to build type for
// new type alias
fun forTypeAlias(modifiedTypeAlias: CirTypeAlias) = forKnownUnderlyingType(modifiedTypeAlias.underlyingType)
// type alias don't needs to be commonized because it is from the standard library
fun forKnownUnderlyingType(underlyingType: CirClassOrTypeAliasType) = object : CommonizedTypeAliasTypeBuilder {
override fun build(typeAliasId: ClassId, arguments: List<CirTypeProjection>, isMarkedNullable: Boolean) =
CirTypeFactory.createTypeAliasType(
typeAliasId = typeAliasId,
underlyingType = underlyingType, // TODO replace arguments???
arguments = arguments,
isMarkedNullable = isMarkedNullable
)
}
}
}
}
private class TypeParameterTypeCommonizer : AbstractStandardCommonizer<CirTypeParameterType, CirTypeParameterType>() {
private lateinit var temp: CirTypeParameterType
override fun commonizationResult() = temp override fun commonizationResult() = temp
override fun initialize(first: CirType) { override fun initialize(first: CirTypeParameterType) {
temp = first temp = first
} }
override fun doCommonizeWith(next: CirType) = areTypesEqual(cache, temp, next) override fun doCommonizeWith(next: CirTypeParameterType): Boolean {
}
/**
* See also [AbstractStrictEqualityTypeChecker].
*/
@Suppress("IntroduceWhenSubject")
internal fun areTypesEqual(cache: CirClassifiersCache, a: CirType, b: CirType): Boolean = when {
a is CirSimpleType -> (b is CirSimpleType) && areSimpleTypesEqual(cache, a, b)
a is CirFlexibleType -> (b is CirFlexibleType)
&& areSimpleTypesEqual(cache, a.lowerBound, b.lowerBound)
&& areSimpleTypesEqual(cache, a.upperBound, b.upperBound)
else -> false
}
private fun areSimpleTypesEqual(cache: CirClassifiersCache, a: CirSimpleType, b: CirSimpleType): Boolean {
val aId = a.classifierId
val bId = b.classifierId
if (a !== b) {
if (a.arguments.size != b.arguments.size || a.isMarkedNullable != b.isMarkedNullable) {
return false
}
if (aId is CirClassifierId.ClassOrTypeAlias) {
if (bId !is CirClassifierId.ClassOrTypeAlias || aId.classId != bId.classId) return false
}
if (aId is CirClassifierId.TypeParameter) {
if (bId !is CirClassifierId.TypeParameter || aId.index != bId.index) return false
}
}
// N.B. only for descriptors that represent classes or type aliases, but not type parameters!
fun isClassOrTypeAliasUnderStandardKotlinPackages(): Boolean {
return (aId as? CirClassifierId.ClassOrTypeAlias)?.classId?.packageFqName?.isUnderStandardKotlinPackages == true
}
fun descriptorsCanBeCommonizedThemselves(): Boolean {
return when (aId) {
is CirClassifierId.Class -> bId is CirClassifierId.Class && cache.classes[aId.classId].canBeCommonized()
is CirClassifierId.TypeAlias -> bId is CirClassifierId.TypeAlias && cache.typeAliases[aId.classId].canBeCommonized()
is CirClassifierId.TypeParameter -> {
// Real type parameter commonization is performed in TypeParameterCommonizer. // Real type parameter commonization is performed in TypeParameterCommonizer.
// Here it is enough to check that FQ names are equal (which is already done above). // Here it is enough to check that type parameter indices and nullability are equal.
true return temp == next
} }
}
}
val descriptorsCanBeCommonized =
/* either class or type alias from Kotlin stdlib */ isClassOrTypeAliasUnderStandardKotlinPackages()
|| /* or descriptors themselves can be commonized */ descriptorsCanBeCommonizedThemselves()
if (!descriptorsCanBeCommonized)
return false
// N.B. both lists of arguments are already known to be of the same size
for (i in a.arguments.indices) {
val aArg = a.arguments[i]
val bArg = b.arguments[i]
if (aArg.isStarProjection != bArg.isStarProjection)
return false
if (!aArg.isStarProjection) {
if (aArg.projectionKind != bArg.projectionKind)
return false
if (!areTypesEqual(cache, aArg.type, bArg.type))
return false
}
}
return true
} }
@Suppress("NOTHING_TO_INLINE") private class FlexibleTypeCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirFlexibleType, CirFlexibleType>() {
private inline fun CirNode<*, *>?.canBeCommonized() = private val lowerBound = TypeCommonizer(cache)
if (this == null) { private val upperBound = TypeCommonizer(cache)
override fun commonizationResult() = CirFlexibleType(
lowerBound = lowerBound.result as CirSimpleType,
upperBound = upperBound.result as CirSimpleType
)
override fun initialize(first: CirFlexibleType) = Unit
override fun doCommonizeWith(next: CirFlexibleType) =
lowerBound.commonizeWith(next.lowerBound) && upperBound.commonizeWith(next.upperBound)
}
private class TypeArgumentCommonizer(cache: CirClassifiersCache) : AbstractStandardCommonizer<CirTypeProjection, CirTypeProjection>() {
private var isStar = false
private lateinit var projectionKind: Variance
private val type = TypeCommonizer(cache)
override fun commonizationResult() = if (isStar) CirStarTypeProjection else CirTypeProjectionImpl(
projectionKind = projectionKind,
type = type.result
)
override fun initialize(first: CirTypeProjection) {
when (first) {
is CirStarTypeProjection -> isStar = true
is CirTypeProjectionImpl -> projectionKind = first.projectionKind
}
}
override fun doCommonizeWith(next: CirTypeProjection) = when (next) {
is CirStarTypeProjection -> isStar
is CirTypeProjectionImpl -> !isStar && projectionKind == next.projectionKind && type.commonizeWith(next.type)
}
}
private class TypeArgumentListCommonizer(cache: CirClassifiersCache) : AbstractListCommonizer<CirTypeProjection, CirTypeProjection>(
singleElementCommonizerFactory = { TypeArgumentCommonizer(cache) }
)
private inline fun <reified T : CirClassifier> commonizeClassifier(
classifierId: ClassId,
classifierNodes: Map<ClassId, CirNode<*, T>>,
): Pair<Boolean, T?> {
if (classifierId.packageFqName.isUnderStandardKotlinPackages) {
/* either class or type alias from Kotlin stdlib */
return true to null
}
/* or descriptors themselves can be commonized */
return when (val node = classifierNodes[classifierId]) {
null -> {
// No node means that the class or type alias was not subject for commonization at all, probably it lays // No node means that the class or type alias was not subject for commonization at all, probably it lays
// not in commonized module descriptors but somewhere in their dependencies. // not in commonized module descriptors but somewhere in their dependencies.
true true to null
} else {
// If entry is present, then contents (common declaration) should not be null.
commonDeclaration() != null
} }
else -> {
// If entry is present, then contents (common declaration) should not be null.
val commonClassifier = node.commonDeclaration()
(commonClassifier != null) to commonClassifier
}
}
}
@@ -12,15 +12,24 @@ import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeSignature import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeSignature
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.types.AbbreviatedType import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
internal inline val KotlinType.declarationDescriptor: ClassifierDescriptor internal inline val KotlinType.declarationDescriptor: ClassifierDescriptor
get() = (constructor.declarationDescriptor ?: error("No declaration descriptor found for $constructor")) get() = (constructor.declarationDescriptor ?: error("No declaration descriptor found for $constructor"))
// eliminate unnecessary repeated abbreviations
internal fun extractExpandedType(abbreviated: AbbreviatedType): SimpleType {
var expanded = abbreviated.expandedType
while (expanded is AbbreviatedType) {
if (expanded.abbreviation.declarationDescriptor !== abbreviated.abbreviation.declarationDescriptor)
break
else
expanded = expanded.expandedType
}
return expanded
}
internal val ClassifierDescriptorWithTypeParameters.internedClassId: ClassId internal val ClassifierDescriptorWithTypeParameters.internedClassId: ClassId
get() = when (val owner = containingDeclaration) { get() = when (val owner = containingDeclaration) {
is PackageFragmentDescriptor -> internedClassId(owner.fqName.intern(), name.intern()) is PackageFragmentDescriptor -> internedClassId(owner.fqName.intern(), name.intern())
@@ -40,3 +40,19 @@ expect fun functionWithTypeParametersInReturnType12(): Box<Fox>
expect fun <T> functionWithUnsubstitutedTypeParametersInReturnType1(): T expect fun <T> functionWithUnsubstitutedTypeParametersInReturnType1(): T
expect fun <T> functionWithUnsubstitutedTypeParametersInReturnType2(): T expect fun <T> functionWithUnsubstitutedTypeParametersInReturnType2(): T
expect fun <T> functionWithUnsubstitutedTypeParametersInReturnType8(): Box<T> expect fun <T> functionWithUnsubstitutedTypeParametersInReturnType8(): Box<T>
expect class Outer<A>() {
class Nested<B>() {
class Nested<C>()
inner class Inner<D>()
}
inner class Inner<E>() {
inner class Inner<F>()
}
}
expect fun <T> returnOuter(): Outer<T>
expect fun <T> returnOuterNested(): Outer.Nested<T>
expect fun <T> returnOuterNestedNested(): Outer.Nested.Nested<T>
expect fun <T, R> returnOuterInner(): Outer<T>.Inner<R>
expect fun <T, R, S> returnOuterInnerInner(): Outer<T>.Inner<R>.Inner<S>
@@ -61,3 +61,19 @@ fun <T> functionWithUnsubstitutedTypeParametersInReturnType6(): T = TODO()
fun <T> functionWithUnsubstitutedTypeParametersInReturnType7(): T = TODO() fun <T> functionWithUnsubstitutedTypeParametersInReturnType7(): T = TODO()
actual fun <T> functionWithUnsubstitutedTypeParametersInReturnType8(): Box<T> = TODO() actual fun <T> functionWithUnsubstitutedTypeParametersInReturnType8(): Box<T> = TODO()
fun <T> functionWithUnsubstitutedTypeParametersInReturnType9(): Box<T> = TODO() fun <T> functionWithUnsubstitutedTypeParametersInReturnType9(): Box<T> = TODO()
actual class Outer<A> actual constructor() {
actual class Nested<B> actual constructor() {
actual class Nested<C> actual constructor()
actual inner class Inner<D> actual constructor()
}
actual inner class Inner<E> actual constructor() {
actual inner class Inner<F> actual constructor()
}
}
actual fun <T> returnOuter(): Outer<T> = TODO()
actual fun <T> returnOuterNested(): Outer.Nested<T> = TODO()
actual fun <T> returnOuterNestedNested(): Outer.Nested.Nested<T> = TODO()
actual fun <T, R> returnOuterInner(): Outer<T>.Inner<R> = TODO()
actual fun <T, R, S> returnOuterInnerInner(): Outer<T>.Inner<R>.Inner<S> = TODO()
@@ -61,3 +61,19 @@ fun <T, Q> functionWithUnsubstitutedTypeParametersInReturnType6(): Q = TODO()
fun functionWithUnsubstitutedTypeParametersInReturnType7(): String = TODO() fun functionWithUnsubstitutedTypeParametersInReturnType7(): String = TODO()
actual fun <T> functionWithUnsubstitutedTypeParametersInReturnType8(): Box<T> = TODO() actual fun <T> functionWithUnsubstitutedTypeParametersInReturnType8(): Box<T> = TODO()
fun functionWithUnsubstitutedTypeParametersInReturnType9(): Box<String> = TODO() fun functionWithUnsubstitutedTypeParametersInReturnType9(): Box<String> = TODO()
actual class Outer<A> actual constructor() {
actual class Nested<B> actual constructor() {
actual class Nested<C> actual constructor()
actual inner class Inner<D> actual constructor()
}
actual inner class Inner<E> actual constructor() {
actual inner class Inner<F> actual constructor()
}
}
actual fun <T> returnOuter(): Outer<T> = TODO()
actual fun <T> returnOuterNested(): Outer.Nested<T> = TODO()
actual fun <T> returnOuterNestedNested(): Outer.Nested.Nested<T> = TODO()
actual fun <T, R> returnOuterInner(): Outer<T>.Inner<R> = TODO()
actual fun <T, R, S> returnOuterInnerInner(): Outer<T>.Inner<R>.Inner<S> = TODO()
@@ -64,3 +64,19 @@ fun <T> functionWithUnsubstitutedTypeParametersInReturnType6(): T = TODO()
fun <T> functionWithUnsubstitutedTypeParametersInReturnType7(): T = TODO() fun <T> functionWithUnsubstitutedTypeParametersInReturnType7(): T = TODO()
fun <T> functionWithUnsubstitutedTypeParametersInReturnType8(): Box<T> = TODO() fun <T> functionWithUnsubstitutedTypeParametersInReturnType8(): Box<T> = TODO()
fun <T> functionWithUnsubstitutedTypeParametersInReturnType9(): Box<T> = TODO() fun <T> functionWithUnsubstitutedTypeParametersInReturnType9(): Box<T> = TODO()
class Outer<A> {
class Nested<B> {
class Nested<C>
inner class Inner<D>
}
inner class Inner<E> {
inner class Inner<F>
}
}
fun <T> returnOuter(): Outer<T> = TODO()
fun <T> returnOuterNested(): Outer.Nested<T> = TODO()
fun <T> returnOuterNestedNested(): Outer.Nested.Nested<T> = TODO()
fun <T, R> returnOuterInner(): Outer<T>.Inner<R> = TODO()
fun <T, R, S> returnOuterInnerInner(): Outer<T>.Inner<R>.Inner<S> = TODO()
@@ -64,3 +64,19 @@ fun <T, Q> functionWithUnsubstitutedTypeParametersInReturnType6(): Q = TODO()
fun functionWithUnsubstitutedTypeParametersInReturnType7(): String = TODO() fun functionWithUnsubstitutedTypeParametersInReturnType7(): String = TODO()
fun <T> functionWithUnsubstitutedTypeParametersInReturnType8(): Box<T> = TODO() fun <T> functionWithUnsubstitutedTypeParametersInReturnType8(): Box<T> = TODO()
fun functionWithUnsubstitutedTypeParametersInReturnType9(): Box<String> = TODO() fun functionWithUnsubstitutedTypeParametersInReturnType9(): Box<String> = TODO()
class Outer<A> {
class Nested<B> {
class Nested<C>
inner class Inner<D>
}
inner class Inner<E> {
inner class Inner<F>
}
}
fun <T> returnOuter(): Outer<T> = TODO()
fun <T> returnOuterNested(): Outer.Nested<T> = TODO()
fun <T> returnOuterNestedNested(): Outer.Nested.Nested<T> = TODO()
fun <T, R> returnOuterInner(): Outer<T>.Inner<R> = TODO()
fun <T, R, S> returnOuterInnerInner(): Outer<T>.Inner<R>.Inner<S> = TODO()
@@ -1,5 +1,12 @@
// this is to avoid missing Kotlin/Native stdlib // this is to avoid missing Kotlin/Native stdlib
package kotlinx.cinterop package kotlinx.cinterop
// fake class with the default constructor and no member scope // fake classes with the default constructor and no member scope
public abstract class CStructVar() abstract class CStructVar
class CPointer<T>
@Suppress("FINAL_UPPER_BOUND") class UByteVarOf<T : UByte>
class UByte
// fake typealiases
typealias CArrayPointer<T> = CPointer<T>
typealias UByteVar = UByteVarOf<UByte>
@@ -42,3 +42,9 @@ typealias Y = V // TA at the RHS with the different nullability of own RHS
// Supertypes: // Supertypes:
expect class FILE : kotlinx.cinterop.CStructVar expect class FILE : kotlinx.cinterop.CStructVar
typealias uuid_t = kotlinx.cinterop.CPointer<kotlinx.cinterop.UByteVarOf<kotlinx.cinterop.UByte>>
// ^^^ TODO: ideally, it should be CArrayPointer<UByteVar>
typealias __darwin_uuid_t = kotlinx.cinterop.CArrayPointer<kotlinx.cinterop.UByteVar>
expect val uuid: uuid_t
@@ -1,5 +1,12 @@
// this is to avoid missing Kotlin/Native stdlib // this is to avoid missing Kotlin/Native stdlib
package kotlinx.cinterop package kotlinx.cinterop
// fake class with the default constructor and no member scope // fake classes with the default constructor and no member scope
public abstract class CStructVar() abstract class CStructVar
class CPointer<T>
@Suppress("FINAL_UPPER_BOUND") class UByteVarOf<T : UByte>
class UByte
// fake typealiases
typealias CArrayPointer<T> = CPointer<T>
typealias UByteVar = UByteVarOf<UByte>
@@ -20,3 +20,5 @@ typealias X = U? // different nullability of the RHS TA
// Supertypes: // Supertypes:
actual typealias FILE = _IO_FILE actual typealias FILE = _IO_FILE
final class _IO_FILE : kotlinx.cinterop.CStructVar {} final class _IO_FILE : kotlinx.cinterop.CStructVar {}
actual val uuid: uuid_t get() = TODO()
@@ -1,5 +1,12 @@
// this is to avoid missing Kotlin/Native stdlib // this is to avoid missing Kotlin/Native stdlib
package kotlinx.cinterop package kotlinx.cinterop
// fake class with the default constructor and no member scope // fake classes with the default constructor and no member scope
public abstract class CStructVar() abstract class CStructVar
class CPointer<T>
@Suppress("FINAL_UPPER_BOUND") class UByteVarOf<T : UByte>
class UByte
// fake typealiases
typealias CArrayPointer<T> = CPointer<T>
typealias UByteVar = UByteVarOf<UByte>
@@ -21,6 +21,8 @@ typealias X = U // different nullability of the RHS TA
actual typealias FILE = __sFILE actual typealias FILE = __sFILE
final class __sFILE : kotlinx.cinterop.CStructVar {} final class __sFILE : kotlinx.cinterop.CStructVar {}
actual val uuid: uuid_t get() = TODO()
// Type alias chain that is present in one target only: // Type alias chain that is present in one target only:
class AA class AA
typealias BB = AA typealias BB = AA
@@ -1,5 +1,12 @@
// this is to avoid missing Kotlin/Native stdlib // this is to avoid missing Kotlin/Native stdlib
package kotlinx.cinterop package kotlinx.cinterop
// fake class with the default constructor and no member scope // fake classes with the default constructor and no member scope
public abstract class CStructVar() abstract class CStructVar
class CPointer<T>
@Suppress("FINAL_UPPER_BOUND") class UByteVarOf<T : UByte>
class UByte
// fake typealiases
typealias CArrayPointer<T> = CPointer<T>
typealias UByteVar = UByteVarOf<UByte>
@@ -51,3 +51,8 @@ typealias Y = V // TA at the RHS with the different nullability of own RHS
// Supertypes: // Supertypes:
typealias FILE = _IO_FILE typealias FILE = _IO_FILE
final class _IO_FILE : kotlinx.cinterop.CStructVar {} final class _IO_FILE : kotlinx.cinterop.CStructVar {}
typealias uuid_t = __darwin_uuid_t
typealias __darwin_uuid_t = kotlinx.cinterop.CArrayPointer<kotlinx.cinterop.UByteVar>
val uuid: uuid_t get() = TODO()
@@ -1,5 +1,12 @@
// this is to avoid missing Kotlin/Native stdlib // this is to avoid missing Kotlin/Native stdlib
package kotlinx.cinterop package kotlinx.cinterop
// fake class with the default constructor and no member scope // fake classes with the default constructor and no member scope
public abstract class CStructVar() abstract class CStructVar
class CPointer<T>
@Suppress("FINAL_UPPER_BOUND") class UByteVarOf<T : UByte>
class UByte
// fake typealiases
typealias CArrayPointer<T> = CPointer<T>
typealias UByteVar = UByteVarOf<UByte>
@@ -52,6 +52,11 @@ typealias Y = V // TA at the RHS with the different nullability of own RHS
typealias FILE = __sFILE typealias FILE = __sFILE
final class __sFILE : kotlinx.cinterop.CStructVar {} final class __sFILE : kotlinx.cinterop.CStructVar {}
typealias uuid_t = __darwin_uuid_t
typealias __darwin_uuid_t = kotlinx.cinterop.CArrayPointer<kotlinx.cinterop.UByteVar>
val uuid: uuid_t get() = TODO()
// Type alias chain that is present in one target only: // Type alias chain that is present in one target only:
class AA class AA
typealias BB = AA typealias BB = AA
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.descriptors.commonizer.core package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation import org.jetbrains.kotlin.descriptors.commonizer.cir.CirAnnotation
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirSimpleType import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassType
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirAnnotationFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirAnnotationFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory
import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType
@@ -290,7 +290,7 @@ private fun mockAnnotation(
constantValueArguments: Map<Name, ConstantValue<*>> = emptyMap(), constantValueArguments: Map<Name, ConstantValue<*>> = emptyMap(),
annotationValueArguments: Map<Name, CirAnnotation> = emptyMap() annotationValueArguments: Map<Name, CirAnnotation> = emptyMap()
): CirAnnotation = CirAnnotationFactory.create( ): CirAnnotation = CirAnnotationFactory.create(
type = CirTypeFactory.create(mockClassType(fqName)) as CirSimpleType, type = CirTypeFactory.create(mockClassType(fqName)) as CirClassType,
constantValueArguments = constantValueArguments, constantValueArguments = constantValueArguments,
annotationValueArguments = annotationValueArguments annotationValueArguments = annotationValueArguments
) )
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirClassFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeAliasFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeAliasFactory
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirRootNode.CirClassifiersCacheImpl import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirRootNode.CirClassifiersCacheImpl
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.buildClassNode import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.buildClassNode
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.buildTypeAliasNode import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.buildTypeAliasNode
@@ -274,7 +275,7 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
@Test @Test
// why success: expect class/actual TAs // why success: expect class/actual TAs
fun taTypesInUserPackageWithDifferentClasses() = doTestSuccess( fun taTypesInUserPackageWithDifferentClasses() = doTestSuccess(
expected = mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo") }, expected = mockClassType("org.sample.FooAlias"),
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo") }, mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo") },
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Bar") } mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Bar") }
) )
@@ -444,7 +445,7 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
@Test @Test
// why success: nullability of underlying type does not matter if expect class/actual TAs created // why success: nullability of underlying type does not matter if expect class/actual TAs created
fun taTypesInUserPackageWithDifferentNullability3() = doTestSuccess( fun taTypesInUserPackageWithDifferentNullability3() = doTestSuccess(
expected = mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = false) }, expected = mockClassType("org.sample.FooAlias"),
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = false) }, mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = false) },
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = true) } mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = true) }
) )
@@ -452,7 +453,7 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
@Test @Test
// why success: nullability of underlying type does not matter if expect class/actual TAs created // why success: nullability of underlying type does not matter if expect class/actual TAs created
fun taTypesInUserPackageWithDifferentNullability4() = doTestSuccess( fun taTypesInUserPackageWithDifferentNullability4() = doTestSuccess(
expected = mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = true) }, expected = mockClassType("org.sample.FooAlias"),
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = true) }, mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = true) },
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = false) } mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = false) }
) )
@@ -520,5 +521,10 @@ class TypeCommonizerTest : AbstractCommonizerTest<CirType, CirType>() {
override fun createCommonizer() = TypeCommonizer(cache) override fun createCommonizer() = TypeCommonizer(cache)
override fun isEqual(a: CirType?, b: CirType?) = (a === b) || (a != null && b != null && areTypesEqual(cache, a, b)) override fun isEqual(a: CirType?, b: CirType?) = (a === b) || (a != null && b != null && areEqual(cache, a, b))
companion object {
fun areEqual(cache: CirClassifiersCache, a: CirType, b: CirType): Boolean =
TypeCommonizer(cache).run { commonizeWith(a) && commonizeWith(b) }
}
} }
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirValueParameter import org.jetbrains.kotlin.descriptors.commonizer.cir.CirValueParameter
import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory import org.jetbrains.kotlin.descriptors.commonizer.cir.factory.CirTypeFactory
import org.jetbrains.kotlin.descriptors.commonizer.core.CirTestValueParameter.Companion.areEqual import org.jetbrains.kotlin.descriptors.commonizer.core.CirTestValueParameter.Companion.areEqual
import org.jetbrains.kotlin.descriptors.commonizer.core.TypeCommonizerTest.Companion.areEqual
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirClassifiersCache
import org.jetbrains.kotlin.descriptors.commonizer.utils.EMPTY_CLASSIFIERS_CACHE import org.jetbrains.kotlin.descriptors.commonizer.utils.EMPTY_CLASSIFIERS_CACHE
import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType import org.jetbrains.kotlin.descriptors.commonizer.utils.mockClassType
@@ -181,7 +182,7 @@ internal data class CirTestValueParameter(
companion object { companion object {
fun areEqual(cache: CirClassifiersCache, a: CirValueParameter, b: CirValueParameter): Boolean { fun areEqual(cache: CirClassifiersCache, a: CirValueParameter, b: CirValueParameter): Boolean {
if (a.name != b.name if (a.name != b.name
|| !areTypesEqual(cache, a.returnType, b.returnType) || !areEqual(cache, a.returnType, b.returnType)
|| a.declaresDefaultValue != b.declaresDefaultValue || a.declaresDefaultValue != b.declaresDefaultValue
|| a.isCrossinline != b.isCrossinline || a.isCrossinline != b.isCrossinline
|| a.isNoinline != b.isNoinline || a.isNoinline != b.isNoinline
@@ -194,7 +195,7 @@ internal data class CirTestValueParameter(
return (aVarargElementType === bVarargElementType) return (aVarargElementType === bVarargElementType)
|| (aVarargElementType != null && bVarargElementType != null || (aVarargElementType != null && bVarargElementType != null
&& areTypesEqual(cache, aVarargElementType, bVarargElementType)) && areEqual(cache, aVarargElementType, bVarargElementType))
} }
} }
} }
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.AbbreviatedType import org.jetbrains.kotlin.types.AbbreviatedType
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SimpleType
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
import kotlin.reflect.KCallable import kotlin.reflect.KCallable
import kotlin.test.fail import kotlin.test.fail
@@ -479,17 +478,6 @@ internal class ComparingDeclarationsVisitor(
context.assertEquals(!expectedAbbreviated.isNull(), !actualAbbreviated.isNull(), "type is abbreviated") context.assertEquals(!expectedAbbreviated.isNull(), !actualAbbreviated.isNull(), "type is abbreviated")
if (expectedAbbreviated != null && actualAbbreviated != null) { if (expectedAbbreviated != null && actualAbbreviated != null) {
fun extractExpandedType(abbreviated: AbbreviatedType): SimpleType { // eliminate unnecessary repeated abbreviations
var expanded = abbreviated.expandedType
while (expanded is AbbreviatedType) {
if (expanded.abbreviation.declarationDescriptor !== abbreviated.abbreviation.declarationDescriptor)
break
else
expanded = expanded.expandedType
}
return expanded
}
visitType( visitType(
expectedAbbreviated.abbreviation, expectedAbbreviated.abbreviation,
actualAbbreviated.abbreviation, actualAbbreviated.abbreviation,