From c69402c8006bfb61a483c4cf0a5e09df4460ee1f Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Fri, 16 Oct 2020 21:26:19 +0300 Subject: [PATCH] [Commonizer] Fix computing underlyingType and expandedType in CirTypeAlias --- .../builder/CommonizedAnnotationDescriptor.kt | 2 +- .../commonizer/builder/builderUtils.kt | 31 ++++--- .../builder/typeAliasDescriptors.kt | 14 ++- .../commonized/macos/package_root.kt | 88 +++++++++++++++++++ .../original/macos/package_root.kt | 88 +++++++++++++++++++ .../utils/ComparingDeclarationsVisitor.kt | 78 ++++++++++------ 6 files changed, 260 insertions(+), 41 deletions(-) diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedAnnotationDescriptor.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedAnnotationDescriptor.kt index 85cfdc7bdce..5ce070970d3 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedAnnotationDescriptor.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/CommonizedAnnotationDescriptor.kt @@ -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 { diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/builderUtils.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/builderUtils.kt index 3adbaadff8e..65a9a910066 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/builderUtils.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/builderUtils.kt @@ -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 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)) } diff --git a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt index 3531ec0d6ec..23c8bc29060 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/typeAliasDescriptors.kt @@ -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: diff --git a/native/commonizer/testData/classifierCommonization/typeAliases/commonized/macos/package_root.kt b/native/commonizer/testData/classifierCommonization/typeAliases/commonized/macos/package_root.kt index 0acee50ce05..7f7bd4eecc3 100644 --- a/native/commonizer/testData/classifierCommonization/typeAliases/commonized/macos/package_root.kt +++ b/native/commonizer/testData/classifierCommonization/typeAliases/commonized/macos/package_root.kt @@ -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 +typealias FF = EE +typealias GG = FF +typealias HH = List +typealias II = HH +typealias JJ = II +typealias KK = HH +typealias LL = II +typealias MM = JJ +typealias NN = (String) -> Int +typealias OO = NN +typealias PP = OO +typealias QQ = (T1) -> T2 +typealias RR = QQ +typealias SS = RR +typealias TT = QQ +typealias UU = RR +typealias VV = SS +typealias WW = TT +typealias XX = UU +typealias YY = VV +typealias ZZ = QQ +typealias AAA = ZZ +typealias BBB = AAA +typealias CCC = QQ +typealias DDD = CCC +typealias EEE = DDD +typealias FFF = RR +typealias GGG = FFF +typealias HHH = GGG +typealias III = RR +typealias JJJ = III +typealias KKK = JJJ +typealias LLL = SS +typealias MMM = LLL +typealias NNN = MMM +typealias OOO = SS +typealias PPP = OOO +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 getHH(): HH = TODO() +fun getII(): II = TODO() +fun getJJ(): JJ = 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 getQQ(): QQ = TODO() +fun getRR(): RR = TODO() +fun getSS(): SS = 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 getZZ(): ZZ = TODO() +fun getAAA(): AAA = TODO() +fun getBBB(): BBB = TODO() +fun getCCC(): CCC = TODO() +fun getDDD(): DDD = TODO() +fun getEEE(): EEE = TODO() +fun getFFF(): FFF = TODO() +fun getGGG(): GGG = TODO() +fun getHHH(): HHH = TODO() +fun getIII(): III = TODO() +fun getJJJ(): JJJ = TODO() +fun getKKK(): KKK = TODO() +fun getLLL(): LLL = TODO() +fun getMMM(): MMM = TODO() +fun getNNN(): NNN = TODO() +fun getOOO(): OOO = TODO() +fun getPPP(): PPP = TODO() +fun getQQQ(): QQQ = TODO() diff --git a/native/commonizer/testData/classifierCommonization/typeAliases/original/macos/package_root.kt b/native/commonizer/testData/classifierCommonization/typeAliases/original/macos/package_root.kt index d30790598a0..af8ddc0560f 100644 --- a/native/commonizer/testData/classifierCommonization/typeAliases/original/macos/package_root.kt +++ b/native/commonizer/testData/classifierCommonization/typeAliases/original/macos/package_root.kt @@ -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 +typealias FF = EE +typealias GG = FF +typealias HH = List +typealias II = HH +typealias JJ = II +typealias KK = HH +typealias LL = II +typealias MM = JJ +typealias NN = (String) -> Int +typealias OO = NN +typealias PP = OO +typealias QQ = (T1) -> T2 +typealias RR = QQ +typealias SS = RR +typealias TT = QQ +typealias UU = RR +typealias VV = SS +typealias WW = TT +typealias XX = UU +typealias YY = VV +typealias ZZ = QQ +typealias AAA = ZZ +typealias BBB = AAA +typealias CCC = QQ +typealias DDD = CCC +typealias EEE = DDD +typealias FFF = RR +typealias GGG = FFF +typealias HHH = GGG +typealias III = RR +typealias JJJ = III +typealias KKK = JJJ +typealias LLL = SS +typealias MMM = LLL +typealias NNN = MMM +typealias OOO = SS +typealias PPP = OOO +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 getHH(): HH = TODO() +fun getII(): II = TODO() +fun getJJ(): JJ = 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 getQQ(): QQ = TODO() +fun getRR(): RR = TODO() +fun getSS(): SS = 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 getZZ(): ZZ = TODO() +fun getAAA(): AAA = TODO() +fun getBBB(): BBB = TODO() +fun getCCC(): CCC = TODO() +fun getDDD(): DDD = TODO() +fun getEEE(): EEE = TODO() +fun getFFF(): FFF = TODO() +fun getGGG(): GGG = TODO() +fun getHHH(): HHH = TODO() +fun getIII(): III = TODO() +fun getJJJ(): JJJ = TODO() +fun getKKK(): KKK = TODO() +fun getLLL(): LLL = TODO() +fun getMMM(): MMM = TODO() +fun getNNN(): NNN = TODO() +fun getOOO(): OOO = TODO() +fun getPPP(): PPP = TODO() +fun getQQQ(): QQQ = TODO() diff --git a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/ComparingDeclarationsVisitor.kt b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/ComparingDeclarationsVisitor.kt index 497c992f9a5..82f84fb9aa0 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/ComparingDeclarationsVisitor.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/utils/ComparingDeclarationsVisitor.kt @@ -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") } )