[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
) : AnnotationDescriptor {
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 {
@@ -87,18 +87,20 @@ internal fun buildDispatchReceiver(callableDescriptor: CallableDescriptor) =
internal fun CirType.buildType(
targetComponents: TargetDeclarationsBuilderComponents,
typeParameterResolver: TypeParameterResolver
typeParameterResolver: TypeParameterResolver,
expandTypeAliases: Boolean = true
): UnwrappedType = when (this) {
is CirSimpleType -> buildType(targetComponents, typeParameterResolver)
is CirSimpleType -> buildType(targetComponents, typeParameterResolver, expandTypeAliases)
is CirFlexibleType -> flexibleType(
lowerBound = lowerBound.buildType(targetComponents, typeParameterResolver),
upperBound = upperBound.buildType(targetComponents, typeParameterResolver)
lowerBound = lowerBound.buildType(targetComponents, typeParameterResolver, expandTypeAliases),
upperBound = upperBound.buildType(targetComponents, typeParameterResolver, expandTypeAliases)
)
}
internal fun CirSimpleType.buildType(
targetComponents: TargetDeclarationsBuilderComponents,
typeParameterResolver: TypeParameterResolver
typeParameterResolver: TypeParameterResolver,
expandTypeAliases: Boolean
): SimpleType {
val classifier: ClassifierDescriptor = when (val classifierId = classifierId) {
is CirClassifierId.Class -> {
@@ -122,17 +124,23 @@ internal fun CirSimpleType.buildType(
}
}
val arguments = arguments.map { it.buildArgument(targetComponents, typeParameterResolver, expandTypeAliases) }
val simpleType = simpleType(
annotations = Annotations.EMPTY,
constructor = classifier.typeConstructor,
arguments = arguments.map { it.buildArgument(targetComponents, typeParameterResolver) },
arguments = arguments,
nullable = isMarkedNullable,
kotlinTypeRefiner = null
)
return if (classifier is TypeAliasDescriptor)
classifier.underlyingType.makeNullableAsSpecified(simpleType.isMarkedNullable).withAbbreviation(simpleType)
else
return if (expandTypeAliases && classifier is TypeAliasDescriptor) {
val expandedType = TypeAliasExpander.NON_REPORTING.expandWithoutAbbreviation(
TypeAliasExpansion.create(null, classifier, arguments),
Annotations.EMPTY
)
expandedType.makeNullableAsSpecified(simpleType.isMarkedNullable).withAbbreviation(simpleType)
} else
simpleType
}
@@ -143,10 +151,11 @@ private inline fun <reified T : ClassifierDescriptorWithTypeParameters> Classifi
private fun CirTypeProjection.buildArgument(
targetComponents: TargetDeclarationsBuilderComponents,
typeParameterResolver: TypeParameterResolver
typeParameterResolver: TypeParameterResolver,
expandTypeAliases: Boolean
): TypeProjection =
if (isStarProjection) {
StarProjectionForAbsentTypeParameter(targetComponents.builtIns)
} 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.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClass
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirClassifier
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.utils.CommonizedGroup
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.types.TypeAliasExpander
import org.jetbrains.kotlin.types.TypeAliasExpansion
internal fun CirTypeAliasNode.buildDescriptors(
components: GlobalDeclarationsBuilderComponents,
@@ -71,13 +74,20 @@ private fun CirTypeAlias.buildDescriptor(
)
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(
declaredTypeParameters = declaredTypeParameters,
underlyingType = lazyUnderlyingType,
expandedType = lazyUnderlyingType
expandedType = lazyExpandedType
)
// cache created type alias descriptor:
@@ -20,3 +20,91 @@ typealias X = U // different nullability of the RHS TA
// Supertypes:
actual typealias FILE = __sFILE
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:
typealias FILE = __sFILE
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.fqNameSafe
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.AbbreviatedType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.getAbbreviation
import org.jetbrains.kotlin.types.SimpleType
import kotlin.contracts.ExperimentalContracts
import kotlin.reflect.KCallable
import kotlin.test.fail
@@ -467,40 +468,63 @@ internal class ComparingDeclarationsVisitor(
check(actual != null && expected != null)
visitAnnotations(
expected.annotations,
actual.annotations,
context.nextLevel("Type annotations")
)
val expectedUnwrapped = expected.getAbbreviation() ?: expected.unwrap()
val actualUnwrapped = actual.getAbbreviation() ?: actual.unwrap()
val expectedUnwrapped = expected.unwrap()
val actualUnwrapped = actual.unwrap()
if (expectedUnwrapped === actualUnwrapped) return
visitAnnotations(
expectedUnwrapped.annotations,
actualUnwrapped.annotations,
context.nextLevel("Unwrapped/unabbreviated type annotations")
)
val expectedAbbreviated = expectedUnwrapped as? AbbreviatedType
val actualAbbreviated = actualUnwrapped as? AbbreviatedType
val expectedId = expectedUnwrapped.declarationDescriptor.run { classId?.asString() ?: name.asString() }
val actualId = actualUnwrapped.declarationDescriptor.run { classId?.asString() ?: name.asString() }
context.assertEquals(!expectedAbbreviated.isNull(), !actualAbbreviated.isNull(), "type is abbreviated")
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
val actualArguments = actualUnwrapped.arguments
visitType(
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 ->
val actualArgument = actualArguments[index]
context.assertEquals(expectedId, actualId, "type class ID / name")
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"))
val expectedArguments = expectedUnwrapped.arguments
val actualArguments = actualUnwrapped.arguments
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)
fail(
buildString {
append("Comparing $subject:\n")
append("Comparing <$subject>:\n")
append("\"$expected\" is not equal to \"$actual\"\n")
}
)