[Commonizer] Initial implementation for nullable return type commonization
^KT-48567
This commit is contained in:
committed by
Space
parent
f56419cbf8
commit
b13f3599cf
+28
-5
@@ -5,21 +5,21 @@
|
||||
|
||||
package org.jetbrains.kotlin.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirFunctionOrProperty
|
||||
import org.jetbrains.kotlin.commonizer.cir.CirName
|
||||
import org.jetbrains.kotlin.commonizer.cir.*
|
||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
|
||||
import org.jetbrains.kotlin.commonizer.utils.safeCastValues
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||
|
||||
abstract class AbstractFunctionOrPropertyCommonizer<T : CirFunctionOrProperty>(
|
||||
classifiers: CirKnownClassifiers
|
||||
) : AbstractStandardCommonizer<T, T>() {
|
||||
) : AbstractStandardCommonizer<T, T?>() {
|
||||
protected lateinit var name: CirName
|
||||
protected val modality = ModalityCommonizer()
|
||||
protected val visibility = VisibilityCommonizer.lowering()
|
||||
protected val extensionReceiver = ExtensionReceiverCommonizer(classifiers)
|
||||
protected val returnType = TypeCommonizer(classifiers).asCommonizer()
|
||||
protected val returnType = ReturnTypeCommonizer(classifiers).asCommonizer()
|
||||
protected lateinit var kind: CallableMemberDescriptor.Kind
|
||||
protected val typeParameters = TypeParameterListCommonizer(classifiers)
|
||||
|
||||
@@ -35,6 +35,29 @@ abstract class AbstractFunctionOrPropertyCommonizer<T : CirFunctionOrProperty>(
|
||||
&& modality.commonizeWith(next.modality)
|
||||
&& visibility.commonizeWith(next)
|
||||
&& extensionReceiver.commonizeWith(next.extensionReceiver)
|
||||
&& returnType.commonizeWith(next.returnType)
|
||||
&& returnType.commonizeWith(next)
|
||||
&& typeParameters.commonizeWith(next.typeParameters)
|
||||
}
|
||||
|
||||
private class ReturnTypeCommonizer(
|
||||
private val classifiers: CirKnownClassifiers,
|
||||
) : NullableContextualSingleInvocationCommonizer<CirFunctionOrProperty, CirType> {
|
||||
override fun invoke(values: List<CirFunctionOrProperty>): CirType? {
|
||||
if (values.isEmpty()) return null
|
||||
val isTopLevel = values.all { it.containingClass == null }
|
||||
val returnTypes = if (isTopLevel) makeNullableIfNecessary(values.map { it.returnType }) else values.map { it.returnType }
|
||||
return TypeCommonizer(classifiers).asCommonizer().commonize(returnTypes)
|
||||
}
|
||||
|
||||
private fun makeNullableIfNecessary(types: List<CirType>): List<CirType> {
|
||||
val simpleTypes = types.safeCastValues<CirType, CirSimpleType>() ?: return types
|
||||
|
||||
if (
|
||||
simpleTypes.all { type -> type.isMarkedNullable } ||
|
||||
simpleTypes.none { type -> type.isMarkedNullable }
|
||||
) return types
|
||||
|
||||
return simpleTypes.map { type -> type.makeNullable() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class FunctionCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP
|
||||
private val modifiers = FunctionModifiersCommonizer()
|
||||
private val valueParameters = CallableValueParametersCommonizer(classifiers)
|
||||
|
||||
override fun commonizationResult(): CirFunction {
|
||||
override fun commonizationResult(): CirFunction? {
|
||||
val valueParameters = valueParameters.result
|
||||
valueParameters.patchCallables()
|
||||
|
||||
@@ -27,7 +27,7 @@ class FunctionCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP
|
||||
valueParameters = valueParameters.valueParameters,
|
||||
hasStableParameterNames = valueParameters.hasStableParameterNames,
|
||||
extensionReceiver = extensionReceiver.result,
|
||||
returnType = returnType.result,
|
||||
returnType = returnType.result ?: return null,
|
||||
kind = kind,
|
||||
modifiers = modifiers.result
|
||||
)
|
||||
|
||||
+18
-1
@@ -19,4 +19,21 @@ fun <T : Any> NullableSingleInvocationCommonizer<T>.asCommonizer(): Commonizer<T
|
||||
collectedValues.add(next)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface NullableContextualSingleInvocationCommonizer<T : Any, R : Any> {
|
||||
operator fun invoke(values: List<T>): R?
|
||||
}
|
||||
|
||||
fun <T : Any, R: Any> NullableContextualSingleInvocationCommonizer<T, R>.asCommonizer(): Commonizer<T, R?> = object : Commonizer<T, R?> {
|
||||
private val collectedValues = mutableListOf<T>()
|
||||
|
||||
override val result: R?
|
||||
get() = this@asCommonizer.invoke(collectedValues)
|
||||
|
||||
override fun commonizeWith(next: T): Boolean {
|
||||
collectedValues.add(next)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ class PropertyCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP
|
||||
private var isExternal = true
|
||||
private lateinit var constCommonizationState: ConstCommonizationState
|
||||
|
||||
override fun commonizationResult(): CirProperty {
|
||||
override fun commonizationResult(): CirProperty? {
|
||||
val modality = modality.result
|
||||
|
||||
val setter = setter.result?.takeIf { setter ->
|
||||
@@ -36,7 +36,7 @@ class PropertyCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP
|
||||
containingClass = null, // does not matter
|
||||
isExternal = isExternal,
|
||||
extensionReceiver = extensionReceiver.result,
|
||||
returnType = returnType.result,
|
||||
returnType = returnType.result ?: return null,
|
||||
kind = kind,
|
||||
isVar = setter != null,
|
||||
isLateInit = false,
|
||||
|
||||
@@ -122,3 +122,21 @@ inline fun <T> Array<T>.fastForEach(action: (T) -> Unit) {
|
||||
action(this[index])
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("unchecked_cast")
|
||||
internal inline fun <T, reified R> List<T>.safeCastValues(): List<R>? {
|
||||
fastForEach { if (it !is R) return null }
|
||||
return this as List<R>
|
||||
}
|
||||
|
||||
|
||||
internal fun <T : Any> List<T>.singleDistinctValueOrNull(): T? = singleDistinctValueOrNull { it }
|
||||
|
||||
internal inline fun <T : Any, R> List<T>.singleDistinctValueOrNull(selector: (T) -> R): R? {
|
||||
if (isEmpty()) return null
|
||||
val value = selector(this[0])
|
||||
for (index in 1 until size) {
|
||||
if (value != selector(this[index])) return null
|
||||
}
|
||||
return value
|
||||
}
|
||||
+4
@@ -96,6 +96,10 @@ abstract class AbstractInlineSourcesCommonizationTest : KtInlineSourceCommonizer
|
||||
}
|
||||
}
|
||||
|
||||
infix fun String.withSource(@Language("kotlin") sourceContent: String) {
|
||||
simpleSingleSourceTarget(this, sourceContent)
|
||||
}
|
||||
|
||||
@InlineSourcesCommonizationTestDsl
|
||||
fun simpleSingleSourceTarget(target: String, @Language("kotlin") sourceCode: String) {
|
||||
simpleSingleSourceTarget(parseCommonizerTarget(target), sourceCode)
|
||||
|
||||
Reference in New Issue
Block a user