[Commonizer] Separate nullability from type substitution
^KT-51686 Verification Pending
This commit is contained in:
committed by
Space
parent
a08fdcf371
commit
25c5d99a0c
@@ -85,27 +85,25 @@ internal tailrec fun computeExpandedType(underlyingType: CirClassOrTypeAliasType
|
||||
internal inline fun CirDeclaration.unsupported(): Nothing = error("This method should never be called on ${this::class.java}, $this")
|
||||
|
||||
internal fun CirClassOrTypeAliasType.withParentArguments(
|
||||
parentArguments: List<CirTypeProjection>, parentIsMarkedNullable: Boolean
|
||||
parentArguments: List<CirTypeProjection>
|
||||
): CirClassOrTypeAliasType {
|
||||
val newIsMarkedNullable = isMarkedNullable || parentIsMarkedNullable
|
||||
|
||||
val newArguments = arguments.map { oldArgument ->
|
||||
if (oldArgument !is CirRegularTypeProjection) return@map oldArgument
|
||||
|
||||
when (val type = oldArgument.type) {
|
||||
is CirTypeParameterType -> parentArguments[type.index]
|
||||
is CirClassOrTypeAliasType -> CirRegularTypeProjection(
|
||||
oldArgument.projectionKind, type.withParentArguments(parentArguments, parentIsMarkedNullable)
|
||||
oldArgument.projectionKind, type.withParentArguments(parentArguments)
|
||||
)
|
||||
else -> oldArgument
|
||||
}
|
||||
}
|
||||
|
||||
return when (val newType = makeNullableIfNecessary(newIsMarkedNullable).withArguments(newArguments)) {
|
||||
return when (val newType = withArguments(newArguments)) {
|
||||
this -> this
|
||||
is CirClassType -> newType
|
||||
is CirTypeAliasType -> newType.withUnderlyingType(
|
||||
newType.underlyingType.withParentArguments(parentArguments, newIsMarkedNullable)
|
||||
newType.underlyingType.withParentArguments(parentArguments)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -90,7 +90,8 @@ internal class ClassOrTypeAliasTypeCommonizer(
|
||||
arguments = arguments,
|
||||
isMarkedNullable = isMarkedNullable,
|
||||
underlyingType = dependencyClassifier.underlyingType.toCirClassOrTypeAliasTypeOrNull(classifiers.commonDependencies)
|
||||
?.withParentArguments(arguments, isMarkedNullable) ?: return null
|
||||
?.makeNullableIfNecessary(isMarkedNullable)
|
||||
?.withParentArguments(arguments) ?: return null
|
||||
)
|
||||
|
||||
else -> Unit
|
||||
@@ -114,7 +115,9 @@ internal class ClassOrTypeAliasTypeCommonizer(
|
||||
typeAliasId = classifierId,
|
||||
arguments = arguments,
|
||||
isMarkedNullable = isMarkedNullable,
|
||||
underlyingType = commonizedClassifier.underlyingType.withParentArguments(arguments, isMarkedNullable)
|
||||
underlyingType = commonizedClassifier.underlyingType
|
||||
.makeNullableIfNecessary(isMarkedNullable)
|
||||
.withParentArguments(arguments)
|
||||
)
|
||||
|
||||
else -> null
|
||||
|
||||
+96
-1
@@ -582,7 +582,7 @@ class ParameterizedTypesCommonizationTest : AbstractInlineSourcesCommonizationTe
|
||||
)
|
||||
}
|
||||
|
||||
fun `test KT-51686`() {
|
||||
fun `test KT-51686 - type argument is parameterized class`() {
|
||||
val result = commonize {
|
||||
outputTarget("(a, b)")
|
||||
"a" withSource """
|
||||
@@ -618,4 +618,99 @@ class ParameterizedTypesCommonizationTest : AbstractInlineSourcesCommonizationTe
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
fun `test KT-51686 - type argument is parameterized class - nullability - 0`() {
|
||||
val result = commonize {
|
||||
outputTarget("(a, b)")
|
||||
"a" withSource """
|
||||
class A
|
||||
class Y<T>
|
||||
class X<T>
|
||||
typealias TA<T> = X<Y<T>>
|
||||
fun f(): TA<A>? = null!!
|
||||
""".trimIndent()
|
||||
|
||||
"b" withSource """
|
||||
class A
|
||||
class Y<T>
|
||||
class X<T>
|
||||
typealias TA<T> = X<Y<T>>
|
||||
fun f(): TA<A>? = null!!
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
result.assertCommonized(
|
||||
"(a, b)", """
|
||||
expect class A()
|
||||
expect class Y<T>()
|
||||
expect class X<T>()
|
||||
typealias TA<T> = X<Y<T>>
|
||||
expect fun f(): TA<A>?
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
fun `test KT-51686 - type argument is parameterized class - nullability - 1`() {
|
||||
val result = commonize {
|
||||
outputTarget("(a, b)")
|
||||
"a" withSource """
|
||||
class A<T>
|
||||
class X<T>
|
||||
typealias TA1<T> = X<T>
|
||||
typealias TA2<T> = X<T>?
|
||||
|
||||
val p1: A<TA1<Unit>> get() = null!!
|
||||
val p2: A<TA1<Unit?> get() = null!!
|
||||
val p3: A<TA1<Unit>?> get() = null!!
|
||||
val p4: A<TA2<Unit>> get() = null!!
|
||||
val p5: A<TA2<Unit?>> get() = null!!
|
||||
val p6: A<TA2<Unit>?> get() = null!!
|
||||
val p7: A<TA1<Unit>>? get() = null!!
|
||||
val p8: TA2<A<Unit>> get() = null!!
|
||||
val p9: TA2<A<Unit>?> get() = null!!
|
||||
val p10: TA2<Unit> get() = null!!
|
||||
fun<T> f1(): A<TA1<TA2<T>>> = null!!
|
||||
""".trimIndent()
|
||||
|
||||
"b" withSource """
|
||||
class A<T>
|
||||
class X<T>
|
||||
typealias TA1<T> = X<T>
|
||||
typealias TA2<T> = X<T>?
|
||||
|
||||
val p1: A<TA1<Unit>> get() = null!!
|
||||
val p2: A<TA1<Unit?> get() = null!!
|
||||
val p3: A<TA1<Unit>?> get() = null!!
|
||||
val p4: A<TA2<Unit>> get() = null!!
|
||||
val p5: A<TA2<Unit?>> get() = null!!
|
||||
val p6: A<TA2<Unit>?> get() = null!!
|
||||
val p7: A<TA1<Unit>>? get() = null!!
|
||||
val p8: TA2<A<Unit>> get() = null!!
|
||||
val p9: TA2<A<Unit>?> get() = null!!
|
||||
val p10: TA2<Unit> get() = null!!
|
||||
fun<T> f1(): A<TA1<TA2<T>>> = null!!
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
result.assertCommonized(
|
||||
"(a, b)", """
|
||||
expect class A<T>()
|
||||
expect class X<T>()
|
||||
typealias TA1<T> = X<T>
|
||||
typealias TA2<T> = X<T>?
|
||||
|
||||
expect val p1: A<TA1<Unit>>
|
||||
expect val p2: A<TA1<Unit?>
|
||||
expect val p3: A<TA1<Unit>?>
|
||||
expect val p4: A<TA2<Unit>?>
|
||||
expect val p5: A<TA2<Unit?>?>
|
||||
expect val p6: A<TA2<Unit>?>
|
||||
expect val p7: A<TA1<Unit>>?
|
||||
expect val p8: TA2<A<Unit>>?
|
||||
expect val p9: TA2<A<Unit>?>?
|
||||
expect val p10: TA2<Unit>?
|
||||
expect fun<T> f1(): A<TA1<TA2<T>?>>
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user