mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
[Commonizer] Avoid leaking non-commonized types as arguments in short-circuited TAs
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
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
|
||||
@@ -22,7 +23,7 @@ abstract class AbstractListCommonizer<T, R>(
|
||||
private var error = false
|
||||
|
||||
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 {
|
||||
if (error)
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.cir.*
|
||||
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.CirTypeFactory
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.CirKnownClassifiers
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
@@ -47,7 +48,7 @@ private class TypeAliasShortCircuitingCommonizer(
|
||||
) : AbstractStandardCommonizer<CirTypeAlias, CirTypeAlias>() {
|
||||
private lateinit var name: Name
|
||||
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 visibility = VisibilityCommonizer.lowering()
|
||||
|
||||
@@ -56,7 +57,7 @@ private class TypeAliasShortCircuitingCommonizer(
|
||||
name = name,
|
||||
typeParameters = typeParameters.result,
|
||||
visibility = visibility.result,
|
||||
underlyingType = computeCommonizedUnderlyingType(underlyingType),
|
||||
underlyingType = underlyingType!!,
|
||||
expandedType = expandedType.result as CirClassType
|
||||
)
|
||||
|
||||
@@ -65,23 +66,74 @@ private class TypeAliasShortCircuitingCommonizer(
|
||||
|
||||
override fun initialize(first: CirTypeAlias) {
|
||||
name = first.name
|
||||
underlyingType = first.underlyingType
|
||||
}
|
||||
|
||||
override fun doCommonizeWith(next: CirTypeAlias) =
|
||||
typeParameters.commonizeWith(next.typeParameters)
|
||||
override fun doCommonizeWith(next: CirTypeAlias): Boolean {
|
||||
if (underlyingType == null) {
|
||||
underlyingType = computeUnderlyingType(next.underlyingType) ?: return false
|
||||
}
|
||||
|
||||
return typeParameters.commonizeWith(next.typeParameters)
|
||||
&& expandedType.commonizeWith(next.expandedType)
|
||||
&& visibility.commonizeWith(next)
|
||||
}
|
||||
|
||||
private tailrec fun computeCommonizedUnderlyingType(underlyingType: CirClassOrTypeAliasType): CirClassOrTypeAliasType {
|
||||
private tailrec fun computeUnderlyingType(underlyingType: CirClassOrTypeAliasType): CirClassOrTypeAliasType? {
|
||||
return when (underlyingType) {
|
||||
is CirClassType -> underlyingType
|
||||
is CirClassType -> underlyingType.withCommonizedArguments()
|
||||
is CirTypeAliasType -> if (classifiers.commonDependeeLibraries.hasClassifier(underlyingType.classifierId))
|
||||
underlyingType
|
||||
underlyingType.withCommonizedArguments()
|
||||
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>() {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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) }
|
||||
)
|
||||
@@ -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.utils.isUnderKotlinNativeSyntheticPackages
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
class TypeCommonizer(private val classifiers: CirKnownClassifiers) : AbstractStandardCommonizer<CirType, 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)
|
||||
}
|
||||
|
||||
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 {
|
||||
if (classifiers.commonDependeeLibraries.hasClassifier(classId)) {
|
||||
// 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)
|
||||
}
|
||||
|
||||
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> =
|
||||
if (isEmpty()) emptyList() else mapNotNullTo(ArrayList(size), transform).compact()
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
typealias my_long_t = common.stuff.MyLong
|
||||
typealias MyTypeAlias = common.stuff.Wrapper<my_long_t>
|
||||
expect val property: MyTypeAlias
|
||||
@@ -0,0 +1,2 @@
|
||||
typealias my_linux_long_t = common.stuff.MyLong
|
||||
actual val property: MyTypeAlias = TODO()
|
||||
@@ -0,0 +1,2 @@
|
||||
typealias my_macos_long_t = common.stuff.MyLong
|
||||
actual val property: MyTypeAlias = TODO()
|
||||
@@ -0,0 +1,4 @@
|
||||
package common.stuff
|
||||
|
||||
class Wrapper<T>
|
||||
class MyLong
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -23,4 +23,6 @@ class ClassifierCommonizationFromSourcesTest : AbstractCommonizationFromSourcesT
|
||||
fun testSupertypes() = doTestSuccessfulCommonization()
|
||||
|
||||
fun testTypeAliases() = doTestSuccessfulCommonization()
|
||||
|
||||
fun testDifferentTypeAliasesInArguments() = doTestSuccessfulCommonization()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user