Skip to content

Commit

Permalink
[Commonizer] Separate nullability from type substitution
Browse files Browse the repository at this point in the history
^KT-51686 Verification Pending

(cherry picked from commit 25c5d99)
  • Loading branch information
sellmair committed Mar 25, 2022
1 parent 2397635 commit 59d0391
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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)
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,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
Expand All @@ -95,7 +96,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 """
Expand Down Expand Up @@ -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()
)
}
}

0 comments on commit 59d0391

Please sign in to comment.