[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
|
package org.jetbrains.kotlin.commonizer.core
|
||||||
|
|
||||||
import org.jetbrains.kotlin.commonizer.cir.CirFunctionOrProperty
|
import org.jetbrains.kotlin.commonizer.cir.*
|
||||||
import org.jetbrains.kotlin.commonizer.cir.CirName
|
|
||||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
|
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
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||||
|
|
||||||
abstract class AbstractFunctionOrPropertyCommonizer<T : CirFunctionOrProperty>(
|
abstract class AbstractFunctionOrPropertyCommonizer<T : CirFunctionOrProperty>(
|
||||||
classifiers: CirKnownClassifiers
|
classifiers: CirKnownClassifiers
|
||||||
) : AbstractStandardCommonizer<T, T>() {
|
) : AbstractStandardCommonizer<T, T?>() {
|
||||||
protected lateinit var name: CirName
|
protected lateinit var name: CirName
|
||||||
protected val modality = ModalityCommonizer()
|
protected val modality = ModalityCommonizer()
|
||||||
protected val visibility = VisibilityCommonizer.lowering()
|
protected val visibility = VisibilityCommonizer.lowering()
|
||||||
protected val extensionReceiver = ExtensionReceiverCommonizer(classifiers)
|
protected val extensionReceiver = ExtensionReceiverCommonizer(classifiers)
|
||||||
protected val returnType = TypeCommonizer(classifiers).asCommonizer()
|
protected val returnType = ReturnTypeCommonizer(classifiers).asCommonizer()
|
||||||
protected lateinit var kind: CallableMemberDescriptor.Kind
|
protected lateinit var kind: CallableMemberDescriptor.Kind
|
||||||
protected val typeParameters = TypeParameterListCommonizer(classifiers)
|
protected val typeParameters = TypeParameterListCommonizer(classifiers)
|
||||||
|
|
||||||
@@ -35,6 +35,29 @@ abstract class AbstractFunctionOrPropertyCommonizer<T : CirFunctionOrProperty>(
|
|||||||
&& modality.commonizeWith(next.modality)
|
&& modality.commonizeWith(next.modality)
|
||||||
&& visibility.commonizeWith(next)
|
&& visibility.commonizeWith(next)
|
||||||
&& extensionReceiver.commonizeWith(next.extensionReceiver)
|
&& extensionReceiver.commonizeWith(next.extensionReceiver)
|
||||||
&& returnType.commonizeWith(next.returnType)
|
&& returnType.commonizeWith(next)
|
||||||
&& typeParameters.commonizeWith(next.typeParameters)
|
&& 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 modifiers = FunctionModifiersCommonizer()
|
||||||
private val valueParameters = CallableValueParametersCommonizer(classifiers)
|
private val valueParameters = CallableValueParametersCommonizer(classifiers)
|
||||||
|
|
||||||
override fun commonizationResult(): CirFunction {
|
override fun commonizationResult(): CirFunction? {
|
||||||
val valueParameters = valueParameters.result
|
val valueParameters = valueParameters.result
|
||||||
valueParameters.patchCallables()
|
valueParameters.patchCallables()
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ class FunctionCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP
|
|||||||
valueParameters = valueParameters.valueParameters,
|
valueParameters = valueParameters.valueParameters,
|
||||||
hasStableParameterNames = valueParameters.hasStableParameterNames,
|
hasStableParameterNames = valueParameters.hasStableParameterNames,
|
||||||
extensionReceiver = extensionReceiver.result,
|
extensionReceiver = extensionReceiver.result,
|
||||||
returnType = returnType.result,
|
returnType = returnType.result ?: return null,
|
||||||
kind = kind,
|
kind = kind,
|
||||||
modifiers = modifiers.result
|
modifiers = modifiers.result
|
||||||
)
|
)
|
||||||
|
|||||||
+18
-1
@@ -19,4 +19,21 @@ fun <T : Any> NullableSingleInvocationCommonizer<T>.asCommonizer(): Commonizer<T
|
|||||||
collectedValues.add(next)
|
collectedValues.add(next)
|
||||||
return true
|
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 var isExternal = true
|
||||||
private lateinit var constCommonizationState: ConstCommonizationState
|
private lateinit var constCommonizationState: ConstCommonizationState
|
||||||
|
|
||||||
override fun commonizationResult(): CirProperty {
|
override fun commonizationResult(): CirProperty? {
|
||||||
val modality = modality.result
|
val modality = modality.result
|
||||||
|
|
||||||
val setter = setter.result?.takeIf { setter ->
|
val setter = setter.result?.takeIf { setter ->
|
||||||
@@ -36,7 +36,7 @@ class PropertyCommonizer(classifiers: CirKnownClassifiers) : AbstractFunctionOrP
|
|||||||
containingClass = null, // does not matter
|
containingClass = null, // does not matter
|
||||||
isExternal = isExternal,
|
isExternal = isExternal,
|
||||||
extensionReceiver = extensionReceiver.result,
|
extensionReceiver = extensionReceiver.result,
|
||||||
returnType = returnType.result,
|
returnType = returnType.result ?: return null,
|
||||||
kind = kind,
|
kind = kind,
|
||||||
isVar = setter != null,
|
isVar = setter != null,
|
||||||
isLateInit = false,
|
isLateInit = false,
|
||||||
|
|||||||
@@ -122,3 +122,21 @@ inline fun <T> Array<T>.fastForEach(action: (T) -> Unit) {
|
|||||||
action(this[index])
|
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
|
@InlineSourcesCommonizationTestDsl
|
||||||
fun simpleSingleSourceTarget(target: String, @Language("kotlin") sourceCode: String) {
|
fun simpleSingleSourceTarget(target: String, @Language("kotlin") sourceCode: String) {
|
||||||
simpleSingleSourceTarget(parseCommonizerTarget(target), sourceCode)
|
simpleSingleSourceTarget(parseCommonizerTarget(target), sourceCode)
|
||||||
|
|||||||
Reference in New Issue
Block a user