[Commonizer] Fix computing underlyingType and expandedType in CirTypeAlias

This commit is contained in:
Dmitriy Dolovov
2020-10-16 21:26:19 +03:00
parent cc4d93ac71
commit c69402c800
6 changed files with 260 additions and 41 deletions
@@ -17,7 +17,7 @@ class CommonizedAnnotationDescriptor(
cirAnnotation: CirAnnotation cirAnnotation: CirAnnotation
) : AnnotationDescriptor { ) : AnnotationDescriptor {
override val type by targetComponents.storageManager.createLazyValue { override val type by targetComponents.storageManager.createLazyValue {
cirAnnotation.type.buildType(targetComponents, TypeParameterResolver.EMPTY) cirAnnotation.type.buildType(targetComponents, TypeParameterResolver.EMPTY, expandTypeAliases = true)
} }
override val allValueArguments by targetComponents.storageManager.createLazyValue { override val allValueArguments by targetComponents.storageManager.createLazyValue {
@@ -87,18 +87,20 @@ internal fun buildDispatchReceiver(callableDescriptor: CallableDescriptor) =
internal fun CirType.buildType( internal fun CirType.buildType(
targetComponents: TargetDeclarationsBuilderComponents, targetComponents: TargetDeclarationsBuilderComponents,
typeParameterResolver: TypeParameterResolver typeParameterResolver: TypeParameterResolver,
expandTypeAliases: Boolean = true
): UnwrappedType = when (this) { ): UnwrappedType = when (this) {
is CirSimpleType -> buildType(targetComponents, typeParameterResolver) is CirSimpleType -> buildType(targetComponents, typeParameterResolver, expandTypeAliases)
is CirFlexibleType -> flexibleType( is CirFlexibleType -> flexibleType(
lowerBound = lowerBound.buildType(targetComponents, typeParameterResolver), lowerBound = lowerBound.buildType(targetComponents, typeParameterResolver, expandTypeAliases),
upperBound = upperBound.buildType(targetComponents, typeParameterResolver) upperBound = upperBound.buildType(targetComponents, typeParameterResolver, expandTypeAliases)
) )
} }
internal fun CirSimpleType.buildType( internal fun CirSimpleType.buildType(
targetComponents: TargetDeclarationsBuilderComponents, targetComponents: TargetDeclarationsBuilderComponents,
typeParameterResolver: TypeParameterResolver typeParameterResolver: TypeParameterResolver,
expandTypeAliases: Boolean
): SimpleType { ): SimpleType {
val classifier: ClassifierDescriptor = when (val classifierId = classifierId) { val classifier: ClassifierDescriptor = when (val classifierId = classifierId) {
is CirClassifierId.Class -> { is CirClassifierId.Class -> {
@@ -122,17 +124,23 @@ internal fun CirSimpleType.buildType(
} }
} }
val arguments = arguments.map { it.buildArgument(targetComponents, typeParameterResolver, expandTypeAliases) }
val simpleType = simpleType( val simpleType = simpleType(
annotations = Annotations.EMPTY, annotations = Annotations.EMPTY,
constructor = classifier.typeConstructor, constructor = classifier.typeConstructor,
arguments = arguments.map { it.buildArgument(targetComponents, typeParameterResolver) }, arguments = arguments,
nullable = isMarkedNullable, nullable = isMarkedNullable,
kotlinTypeRefiner = null kotlinTypeRefiner = null
) )
return if (classifier is TypeAliasDescriptor) return if (expandTypeAliases && classifier is TypeAliasDescriptor) {
classifier.underlyingType.makeNullableAsSpecified(simpleType.isMarkedNullable).withAbbreviation(simpleType) val expandedType = TypeAliasExpander.NON_REPORTING.expandWithoutAbbreviation(
else TypeAliasExpansion.create(null, classifier, arguments),
Annotations.EMPTY
)
expandedType.makeNullableAsSpecified(simpleType.isMarkedNullable).withAbbreviation(simpleType)
} else
simpleType simpleType
} }
@@ -143,10 +151,11 @@ private inline fun <reified T : ClassifierDescriptorWithTypeParameters> Classifi
private fun CirTypeProjection.buildArgument( private fun CirTypeProjection.buildArgument(
targetComponents: TargetDeclarationsBuilderComponents, targetComponents: TargetDeclarationsBuilderComponents,
typeParameterResolver: TypeParameterResolver typeParameterResolver: TypeParameterResolver,
expandTypeAliases: Boolean
): TypeProjection = ): TypeProjection =
if (isStarProjection) { if (isStarProjection) {
StarProjectionForAbsentTypeParameter(targetComponents.builtIns) StarProjectionForAbsentTypeParameter(targetComponents.builtIns)
} else { } else {
TypeProjectionImpl(projectionKind, type.buildType(targetComponents, typeParameterResolver)) TypeProjectionImpl(projectionKind, type.buildType(targetComponents, typeParameterResolver, expandTypeAliases))
} }
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.builder
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifier import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifier
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeAlias import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeAlias
@@ -14,6 +15,8 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirTypeAliasNode
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion.indexOfCommon import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirNode.Companion.indexOfCommon
import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup import org.jetbrains.kotlin.descriptors.commonizer.utils.CommonizedGroup
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.types.TypeAliasExpander
import org.jetbrains.kotlin.types.TypeAliasExpansion
internal fun CirTypeAliasNode.buildDescriptors( internal fun CirTypeAliasNode.buildDescriptors(
components: GlobalDeclarationsBuilderComponents, components: GlobalDeclarationsBuilderComponents,
@@ -71,13 +74,20 @@ private fun CirTypeAlias.buildDescriptor(
) )
val lazyUnderlyingType = storageManager.createLazyValue { val lazyUnderlyingType = storageManager.createLazyValue {
underlyingType.buildType(targetComponents, typeParameterResolver) underlyingType.buildType(targetComponents, typeParameterResolver, expandTypeAliases = false)
}
val lazyExpandedType = storageManager.createLazyValue {
TypeAliasExpander.NON_REPORTING.expandWithoutAbbreviation(
TypeAliasExpansion.createWithFormalArguments(typeAliasDescriptor),
Annotations.EMPTY
)
} }
typeAliasDescriptor.initialize( typeAliasDescriptor.initialize(
declaredTypeParameters = declaredTypeParameters, declaredTypeParameters = declaredTypeParameters,
underlyingType = lazyUnderlyingType, underlyingType = lazyUnderlyingType,
expandedType = lazyUnderlyingType expandedType = lazyExpandedType
) )
// cache created type alias descriptor: // cache created type alias descriptor:
@@ -20,3 +20,91 @@ typealias X = U // different nullability of the RHS TA
// Supertypes: // Supertypes:
actual typealias FILE = __sFILE actual typealias FILE = __sFILE
final class __sFILE : kotlinx.cinterop.CStructVar {} final class __sFILE : kotlinx.cinterop.CStructVar {}
// Type alias chain that is present in one target only:
class AA
typealias BB = AA
typealias CC = BB
typealias DD = CC
typealias EE = List<String>
typealias FF = EE
typealias GG = FF
typealias HH<T> = List<T>
typealias II<R> = HH<R>
typealias JJ<S> = II<S>
typealias KK = HH<String>
typealias LL = II<String>
typealias MM = JJ<String>
typealias NN = (String) -> Int
typealias OO = NN
typealias PP = OO
typealias QQ<T1, T2> = (T1) -> T2
typealias RR<R1, R2> = QQ<R1, R2>
typealias SS<S1, S2> = RR<S1, S2>
typealias TT = QQ<String, Int>
typealias UU = RR<String, Int>
typealias VV = SS<String, Int>
typealias WW = TT
typealias XX = UU
typealias YY = VV
typealias ZZ<T> = QQ<T, Int>
typealias AAA = ZZ<String>
typealias BBB = AAA
typealias CCC<T> = QQ<String, T>
typealias DDD = CCC<Int>
typealias EEE = DDD
typealias FFF<R> = RR<R, Int>
typealias GGG = FFF<String>
typealias HHH = GGG
typealias III<R> = RR<String, R>
typealias JJJ = III<Int>
typealias KKK = JJJ
typealias LLL<S> = SS<S, Int>
typealias MMM = LLL<String>
typealias NNN = MMM
typealias OOO<S> = SS<String, S>
typealias PPP = OOO<Int>
typealias QQQ = PPP
fun getBB(): BB = TODO()
fun getCC(): CC = TODO()
fun getDD(): DD = TODO()
fun getEE(): EE = TODO()
fun getFF(): FF = TODO()
fun getGG(): GG = TODO()
fun <U> getHH(): HH<U> = TODO()
fun <V> getII(): II<V> = TODO()
fun <W> getJJ(): JJ<W> = TODO()
fun getKK(): KK = TODO()
fun getLL(): LL = TODO()
fun getMM(): MM = TODO()
fun getNN(): NN = TODO()
fun getOO(): OO = TODO()
fun getPP(): PP = TODO()
fun <U1, U2> getQQ(): QQ<U1, U2> = TODO()
fun <V1, V2> getRR(): RR<V1, V2> = TODO()
fun <W1, W2> getSS(): SS<W1, W2> = TODO()
fun getTT(): TT = TODO()
fun getUU(): UU = TODO()
fun getVV(): VV = TODO()
fun getWW(): WW = TODO()
fun getXX(): XX = TODO()
fun getYY(): YY = TODO()
fun <U> getZZ(): ZZ<U> = TODO()
fun getAAA(): AAA = TODO()
fun getBBB(): BBB = TODO()
fun <U> getCCC(): CCC<U> = TODO()
fun getDDD(): DDD = TODO()
fun getEEE(): EEE = TODO()
fun <V> getFFF(): FFF<V> = TODO()
fun getGGG(): GGG = TODO()
fun getHHH(): HHH = TODO()
fun <V> getIII(): III<V> = TODO()
fun getJJJ(): JJJ = TODO()
fun getKKK(): KKK = TODO()
fun <W> getLLL(): LLL<W> = TODO()
fun getMMM(): MMM = TODO()
fun getNNN(): NNN = TODO()
fun <W> getOOO(): OOO<W> = TODO()
fun getPPP(): PPP = TODO()
fun getQQQ(): QQQ = TODO()
@@ -40,3 +40,91 @@ typealias Y = V // TA at the RHS with the different nullability of own RHS
// Supertypes: // Supertypes:
typealias FILE = __sFILE typealias FILE = __sFILE
final class __sFILE : kotlinx.cinterop.CStructVar {} final class __sFILE : kotlinx.cinterop.CStructVar {}
// Type alias chain that is present in one target only:
class AA
typealias BB = AA
typealias CC = BB
typealias DD = CC
typealias EE = List<String>
typealias FF = EE
typealias GG = FF
typealias HH<T> = List<T>
typealias II<R> = HH<R>
typealias JJ<S> = II<S>
typealias KK = HH<String>
typealias LL = II<String>
typealias MM = JJ<String>
typealias NN = (String) -> Int
typealias OO = NN
typealias PP = OO
typealias QQ<T1, T2> = (T1) -> T2
typealias RR<R1, R2> = QQ<R1, R2>
typealias SS<S1, S2> = RR<S1, S2>
typealias TT = QQ<String, Int>
typealias UU = RR<String, Int>
typealias VV = SS<String, Int>
typealias WW = TT
typealias XX = UU
typealias YY = VV
typealias ZZ<T> = QQ<T, Int>
typealias AAA = ZZ<String>
typealias BBB = AAA
typealias CCC<T> = QQ<String, T>
typealias DDD = CCC<Int>
typealias EEE = DDD
typealias FFF<R> = RR<R, Int>
typealias GGG = FFF<String>
typealias HHH = GGG
typealias III<R> = RR<String, R>
typealias JJJ = III<Int>
typealias KKK = JJJ
typealias LLL<S> = SS<S, Int>
typealias MMM = LLL<String>
typealias NNN = MMM
typealias OOO<S> = SS<String, S>
typealias PPP = OOO<Int>
typealias QQQ = PPP
fun getBB(): BB = TODO()
fun getCC(): CC = TODO()
fun getDD(): DD = TODO()
fun getEE(): EE = TODO()
fun getFF(): FF = TODO()
fun getGG(): GG = TODO()
fun <U> getHH(): HH<U> = TODO()
fun <V> getII(): II<V> = TODO()
fun <W> getJJ(): JJ<W> = TODO()
fun getKK(): KK = TODO()
fun getLL(): LL = TODO()
fun getMM(): MM = TODO()
fun getNN(): NN = TODO()
fun getOO(): OO = TODO()
fun getPP(): PP = TODO()
fun <U1, U2> getQQ(): QQ<U1, U2> = TODO()
fun <V1, V2> getRR(): RR<V1, V2> = TODO()
fun <W1, W2> getSS(): SS<W1, W2> = TODO()
fun getTT(): TT = TODO()
fun getUU(): UU = TODO()
fun getVV(): VV = TODO()
fun getWW(): WW = TODO()
fun getXX(): XX = TODO()
fun getYY(): YY = TODO()
fun <U> getZZ(): ZZ<U> = TODO()
fun getAAA(): AAA = TODO()
fun getBBB(): BBB = TODO()
fun <U> getCCC(): CCC<U> = TODO()
fun getDDD(): DDD = TODO()
fun getEEE(): EEE = TODO()
fun <V> getFFF(): FFF<V> = TODO()
fun getGGG(): GGG = TODO()
fun getHHH(): HHH = TODO()
fun <V> getIII(): III<V> = TODO()
fun getJJJ(): JJJ = TODO()
fun getKKK(): KKK = TODO()
fun <W> getLLL(): LLL<W> = TODO()
fun getMMM(): MMM = TODO()
fun getNNN(): NNN = TODO()
fun <W> getOOO(): OOO<W> = TODO()
fun getPPP(): PPP = TODO()
fun getQQQ(): QQQ = TODO()
@@ -16,8 +16,9 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe 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.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.getAbbreviation 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
@@ -467,40 +468,63 @@ internal class ComparingDeclarationsVisitor(
check(actual != null && expected != null) check(actual != null && expected != null)
visitAnnotations( val expectedUnwrapped = expected.unwrap()
expected.annotations, val actualUnwrapped = actual.unwrap()
actual.annotations,
context.nextLevel("Type annotations")
)
val expectedUnwrapped = expected.getAbbreviation() ?: expected.unwrap()
val actualUnwrapped = actual.getAbbreviation() ?: actual.unwrap()
if (expectedUnwrapped === actualUnwrapped) return if (expectedUnwrapped === actualUnwrapped) return
visitAnnotations( val expectedAbbreviated = expectedUnwrapped as? AbbreviatedType
expectedUnwrapped.annotations, val actualAbbreviated = actualUnwrapped as? AbbreviatedType
actualUnwrapped.annotations,
context.nextLevel("Unwrapped/unabbreviated type annotations")
)
val expectedId = expectedUnwrapped.declarationDescriptor.run { classId?.asString() ?: name.asString() } context.assertEquals(!expectedAbbreviated.isNull(), !actualAbbreviated.isNull(), "type is abbreviated")
val actualId = actualUnwrapped.declarationDescriptor.run { classId?.asString() ?: name.asString() }
context.assertEquals(expectedId, actualId, "type class ID / name") 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
}
val expectedArguments = expectedUnwrapped.arguments visitType(
val actualArguments = actualUnwrapped.arguments expectedAbbreviated.abbreviation,
actualAbbreviated.abbreviation,
context.nextLevel("Abbreviation type")
)
visitType(
extractExpandedType(expectedAbbreviated),
extractExpandedType(actualAbbreviated),
context.nextLevel("Expanded type")
)
} else {
visitAnnotations(
expectedUnwrapped.annotations,
actualUnwrapped.annotations,
context.nextLevel("Type annotations")
)
context.assertEquals(expectedArguments.size, actualArguments.size, "size of type arguments list") val expectedId = expectedUnwrapped.declarationDescriptor.run { classId?.asString() ?: name.asString() }
val actualId = actualUnwrapped.declarationDescriptor.run { classId?.asString() ?: name.asString() }
expectedArguments.forEachIndexed { index, expectedArgument -> context.assertEquals(expectedId, actualId, "type class ID / name")
val actualArgument = actualArguments[index]
context.assertFieldsEqual(expectedArgument::isStarProjection, actualArgument::isStarProjection) val expectedArguments = expectedUnwrapped.arguments
if (!expectedArgument.isStarProjection) { val actualArguments = actualUnwrapped.arguments
context.assertFieldsEqual(expectedArgument::getProjectionKind, actualArgument::getProjectionKind)
visitType(expectedArgument.type, actualArgument.type, context.nextLevel("Type argument type")) context.assertEquals(expectedArguments.size, actualArguments.size, "size of type arguments list")
expectedArguments.forEachIndexed { index, expectedArgument ->
val actualArgument = actualArguments[index]
context.assertFieldsEqual(expectedArgument::isStarProjection, actualArgument::isStarProjection)
if (!expectedArgument.isStarProjection) {
context.assertFieldsEqual(expectedArgument::getProjectionKind, actualArgument::getProjectionKind)
visitType(expectedArgument.type, actualArgument.type, context.nextLevel("Type argument type"))
}
} }
} }
} }
@@ -509,7 +533,7 @@ internal class ComparingDeclarationsVisitor(
if (expected != actual) if (expected != actual)
fail( fail(
buildString { buildString {
append("Comparing $subject:\n") append("Comparing <$subject>:\n")
append("\"$expected\" is not equal to \"$actual\"\n") append("\"$expected\" is not equal to \"$actual\"\n")
} }
) )