[Commonizer] Avoid leaking non-commonized types as arguments in short-circuited TAs
This commit is contained in:
+2
-1
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
|
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirType
|
||||||
|
import org.jetbrains.kotlin.descriptors.commonizer.utils.compactMap
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unlike [Commonizer] which commonizes only single elements, this [AbstractListCommonizer] commonizes lists of elements using
|
* Unlike [Commonizer] which commonizes only single elements, this [AbstractListCommonizer] commonizes lists of elements using
|
||||||
@@ -22,7 +23,7 @@ abstract class AbstractListCommonizer<T, R>(
|
|||||||
private var error = false
|
private var error = false
|
||||||
|
|
||||||
final override val result: List<R>
|
final override val result: List<R>
|
||||||
get() = checkState(commonizers, error).map { it.result }
|
get() = checkState(commonizers, error).compactMap { it.result }
|
||||||
|
|
||||||
final override fun commonizeWith(next: List<T>): Boolean {
|
final override fun commonizeWith(next: List<T>): Boolean {
|
||||||
if (error)
|
if (error)
|
||||||
|
|||||||
+61
-9
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.Modality
|
|||||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
|
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.cir.factory.CirTypeFactory
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
|
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ private class TypeAliasShortCircuitingCommonizer(
|
|||||||
) : AbstractStandardCommonizer<CirTypeAlias, CirTypeAlias>() {
|
) : AbstractStandardCommonizer<CirTypeAlias, CirTypeAlias>() {
|
||||||
private lateinit var name: Name
|
private lateinit var name: Name
|
||||||
private val typeParameters = TypeParameterListCommonizer(classifiers)
|
private val typeParameters = TypeParameterListCommonizer(classifiers)
|
||||||
private lateinit var underlyingType: CirClassOrTypeAliasType
|
private var underlyingType: CirClassOrTypeAliasType? = null // null means not computed yet
|
||||||
private val expandedType = TypeCommonizer(classifiers)
|
private val expandedType = TypeCommonizer(classifiers)
|
||||||
private val visibility = VisibilityCommonizer.lowering()
|
private val visibility = VisibilityCommonizer.lowering()
|
||||||
|
|
||||||
@@ -56,7 +57,7 @@ private class TypeAliasShortCircuitingCommonizer(
|
|||||||
name = name,
|
name = name,
|
||||||
typeParameters = typeParameters.result,
|
typeParameters = typeParameters.result,
|
||||||
visibility = visibility.result,
|
visibility = visibility.result,
|
||||||
underlyingType = computeCommonizedUnderlyingType(underlyingType),
|
underlyingType = underlyingType!!,
|
||||||
expandedType = expandedType.result as CirClassType
|
expandedType = expandedType.result as CirClassType
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -65,23 +66,74 @@ private class TypeAliasShortCircuitingCommonizer(
|
|||||||
|
|
||||||
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): Boolean {
|
||||||
typeParameters.commonizeWith(next.typeParameters)
|
if (underlyingType == null) {
|
||||||
|
underlyingType = computeUnderlyingType(next.underlyingType) ?: return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return 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 {
|
private tailrec fun computeUnderlyingType(underlyingType: CirClassOrTypeAliasType): CirClassOrTypeAliasType? {
|
||||||
return when (underlyingType) {
|
return when (underlyingType) {
|
||||||
is CirClassType -> underlyingType
|
is CirClassType -> underlyingType.withCommonizedArguments()
|
||||||
is CirTypeAliasType -> if (classifiers.commonDependeeLibraries.hasClassifier(underlyingType.classifierId))
|
is CirTypeAliasType -> if (classifiers.commonDependeeLibraries.hasClassifier(underlyingType.classifierId))
|
||||||
underlyingType
|
underlyingType.withCommonizedArguments()
|
||||||
else
|
else
|
||||||
computeCommonizedUnderlyingType(underlyingType.underlyingType)
|
computeUnderlyingType(underlyingType.underlyingType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun CirClassType.withCommonizedArguments(): CirClassType? {
|
||||||
|
val existingArguments = arguments
|
||||||
|
val newArguments = existingArguments.toCommonizedArguments() ?: return null
|
||||||
|
|
||||||
|
val existingOuterType = outerType
|
||||||
|
val newOuterType = existingOuterType?.let { it.withCommonizedArguments() ?: return null }
|
||||||
|
|
||||||
|
return if (newArguments !== existingArguments || newOuterType !== existingOuterType)
|
||||||
|
CirTypeFactory.createClassType(
|
||||||
|
classId = classifierId,
|
||||||
|
outerType = newOuterType,
|
||||||
|
visibility = visibility,
|
||||||
|
arguments = newArguments,
|
||||||
|
isMarkedNullable = isMarkedNullable
|
||||||
|
)
|
||||||
|
else
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun CirTypeAliasType.withCommonizedArguments(): CirTypeAliasType? {
|
||||||
|
val existingArguments = arguments
|
||||||
|
val newArguments = existingArguments.toCommonizedArguments() ?: return null
|
||||||
|
|
||||||
|
val existingUnderlyingType = underlyingType
|
||||||
|
val newUnderlyingType = when (existingUnderlyingType) {
|
||||||
|
is CirClassType -> existingUnderlyingType.withCommonizedArguments()
|
||||||
|
is CirTypeAliasType -> existingUnderlyingType.withCommonizedArguments()
|
||||||
|
} ?: return null
|
||||||
|
|
||||||
|
return if (newArguments !== existingArguments || newUnderlyingType !== existingUnderlyingType)
|
||||||
|
CirTypeFactory.createTypeAliasType(
|
||||||
|
typeAliasId = classifierId,
|
||||||
|
underlyingType = newUnderlyingType,
|
||||||
|
arguments = newArguments,
|
||||||
|
isMarkedNullable = isMarkedNullable
|
||||||
|
)
|
||||||
|
else
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
private inline fun List<CirTypeProjection>.toCommonizedArguments(): List<CirTypeProjection>? =
|
||||||
|
if (isEmpty())
|
||||||
|
this
|
||||||
|
else
|
||||||
|
TypeArgumentListCommonizer(classifiers).let { if (it.commonizeWith(this)) it.result else null }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TypeAliasLiftingUpCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirTypeAlias, CirTypeAlias>() {
|
private class TypeAliasLiftingUpCommonizer(classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirTypeAlias, CirTypeAlias>() {
|
||||||
|
|||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.core
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirStarTypeProjection
|
||||||
|
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeProjection
|
||||||
|
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeProjectionImpl
|
||||||
|
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
|
||||||
|
class TypeArgumentCommonizer(
|
||||||
|
classifiers: CirKnownClassifiers
|
||||||
|
) : AbstractStandardCommonizer<CirTypeProjection, CirTypeProjection>() {
|
||||||
|
private var isStar = false
|
||||||
|
private lateinit var projectionKind: Variance
|
||||||
|
private val type = TypeCommonizer(classifiers)
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.core
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.commonizer.cir.CirTypeProjection
|
||||||
|
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
|
||||||
|
|
||||||
|
class TypeArgumentListCommonizer(classifiers: CirKnownClassifiers) : AbstractListCommonizer<CirTypeProjection, CirTypeProjection>(
|
||||||
|
singleElementCommonizerFactory = { TypeArgumentCommonizer(classifiers) }
|
||||||
|
)
|
||||||
-30
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizedTypeAliasAnswe
|
|||||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
|
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
|
||||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderKotlinNativeSyntheticPackages
|
import org.jetbrains.kotlin.descriptors.commonizer.utils.isUnderKotlinNativeSyntheticPackages
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.types.Variance
|
|
||||||
|
|
||||||
class TypeCommonizer(private val classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirType, CirType>() {
|
class TypeCommonizer(private val classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirType, CirType>() {
|
||||||
private lateinit var wrapped: Commonizer<*, CirType>
|
private lateinit var wrapped: Commonizer<*, CirType>
|
||||||
@@ -190,35 +189,6 @@ private class FlexibleTypeCommonizer(classifiers: CirKnownClassifiers) : Abstrac
|
|||||||
lowerBound.commonizeWith(next.lowerBound) && upperBound.commonizeWith(next.upperBound)
|
lowerBound.commonizeWith(next.lowerBound) && upperBound.commonizeWith(next.upperBound)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TypeArgumentCommonizer(
|
|
||||||
classifiers: CirKnownClassifiers
|
|
||||||
) : AbstractStandardCommonizer<CirTypeProjection, CirTypeProjection>() {
|
|
||||||
private var isStar = false
|
|
||||||
private lateinit var projectionKind: Variance
|
|
||||||
private val type = TypeCommonizer(classifiers)
|
|
||||||
|
|
||||||
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(classifiers: CirKnownClassifiers) : AbstractListCommonizer<CirTypeProjection, CirTypeProjection>(
|
|
||||||
singleElementCommonizerFactory = { TypeArgumentCommonizer(classifiers) }
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun commonizeClass(classId: ClassId, classifiers: CirKnownClassifiers): Boolean {
|
private fun commonizeClass(classId: ClassId, classifiers: CirKnownClassifiers): Boolean {
|
||||||
if (classifiers.commonDependeeLibraries.hasClassifier(classId)) {
|
if (classifiers.commonDependeeLibraries.hasClassifier(classId)) {
|
||||||
// The class is from common fragment of dependee library (ex: stdlib). Already commonized.
|
// The class is from common fragment of dependee library (ex: stdlib). Already commonized.
|
||||||
|
|||||||
@@ -41,6 +41,13 @@ internal inline fun <T, R> Collection<T>.compactMap(transform: (T) -> R): List<R
|
|||||||
else -> mapTo(ArrayList(size), transform)
|
else -> mapTo(ArrayList(size), transform)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal inline fun <T, R> Array<T>.compactMap(transform: (T) -> R): List<R> =
|
||||||
|
when (size) {
|
||||||
|
0 -> emptyList()
|
||||||
|
1 -> singletonList(transform(this[0]))
|
||||||
|
else -> mapTo(ArrayList(size), transform)
|
||||||
|
}
|
||||||
|
|
||||||
internal inline fun <T, reified R : Any> Collection<T>.compactMapNotNull(transform: (T) -> R?): List<R> =
|
internal inline fun <T, reified R : Any> Collection<T>.compactMapNotNull(transform: (T) -> R?): List<R> =
|
||||||
if (isEmpty()) emptyList() else mapNotNullTo(ArrayList(size), transform).compact()
|
if (isEmpty()) emptyList() else mapNotNullTo(ArrayList(size), transform).compact()
|
||||||
|
|
||||||
|
|||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
typealias my_long_t = common.stuff.MyLong
|
||||||
|
typealias MyTypeAlias = common.stuff.Wrapper<my_long_t>
|
||||||
|
expect val property: MyTypeAlias
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
typealias my_linux_long_t = common.stuff.MyLong
|
||||||
|
actual val property: MyTypeAlias = TODO()
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
typealias my_macos_long_t = common.stuff.MyLong
|
||||||
|
actual val property: MyTypeAlias = TODO()
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package common.stuff
|
||||||
|
|
||||||
|
class Wrapper<T>
|
||||||
|
class MyLong
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
typealias my_long_t = my_linux_long_t
|
||||||
|
typealias my_linux_long_t = common.stuff.MyLong
|
||||||
|
typealias MyTypeAlias = common.stuff.Wrapper<my_long_t>
|
||||||
|
val property: MyTypeAlias = TODO()
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
typealias my_long_t = my_macos_long_t
|
||||||
|
typealias my_macos_long_t = common.stuff.MyLong
|
||||||
|
typealias MyTypeAlias = common.stuff.Wrapper<my_long_t>
|
||||||
|
val property: MyTypeAlias = TODO()
|
||||||
+2
@@ -23,4 +23,6 @@ class ClassifierCommonizationFromSourcesTest : AbstractCommonizationFromSourcesT
|
|||||||
fun testSupertypes() = doTestSuccessfulCommonization()
|
fun testSupertypes() = doTestSuccessfulCommonization()
|
||||||
|
|
||||||
fun testTypeAliases() = doTestSuccessfulCommonization()
|
fun testTypeAliases() = doTestSuccessfulCommonization()
|
||||||
|
|
||||||
|
fun testDifferentTypeAliasesInArguments() = doTestSuccessfulCommonization()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user