From 9c6df5313a5e1e0eaeffa167222de33f5cfca5f9 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Fri, 16 Sep 2022 19:14:30 +0200 Subject: [PATCH] [FIR] Fix substitution of anonymous type's supertypes, ^KT-51418 Fixed --- .../jetbrains/kotlin/fir/types/TypeUtils.kt | 42 +++++++++++++++---- ...ForReturnTypeOfSingleExpressionFunction.kt | 15 ++++++- ...orReturnTypeOfSingleExpressionFunction.txt | 20 +++++++++ 3 files changed, 68 insertions(+), 9 deletions(-) diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt index db5f96a8c09..f77e997f10b 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt @@ -411,16 +411,42 @@ private fun ConeKotlinType.approximateToOnlySupertype(session: FirSession): Cone return null } val result = superType.type.withNullability(nullability, session.typeContext) - val resultTypeArguments = result.typeArguments - if (resultTypeArguments.isNotEmpty() && resultTypeArguments.size == typeArguments.size) { + if (typeArguments.isNotEmpty()) { val substitution = mutableMapOf() - for (index in resultTypeArguments.indices) { - // TODO: this is not correct (should use firClass' arguments as keys); see comment in KT-51418 - val key = resultTypeArguments[index] - val value = typeArguments[index] - val symbol = (key as? ConeTypeParameterType)?.lookupTag?.typeParameterSymbol ?: continue - substitution[symbol] = value.type!! + + var index = 0 + fun addSubstitution(projection: ConeTypeProjection): Boolean { + when (projection) { + is ConeTypeParameterType -> { + val symbol = projection.lookupTag.typeParameterSymbol + if (!substitution.containsKey(symbol)) { + substitution[symbol] = typeArguments[index].type!! + index++ + } + } + is ConeErrorType -> { + return false + } + is ConeClassLikeType -> { + for (typeArgument in projection.typeArguments) { + if (!addSubstitution(typeArgument)) { + return false + } + } + } + is ConeKotlinTypeProjection -> { + if (!addSubstitution(projection.type)) { + return false + } + } + is ConeStarProjection -> { + index++ + } + } + return true } + + addSubstitution(result) return ConeSubstitutorByMap(substitution, session).substituteOrSelf(result) } return result diff --git a/compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt b/compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt index 765400e1848..cda7d5ab8f7 100644 --- a/compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt +++ b/compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.kt @@ -27,4 +27,17 @@ class FieldTest { private val ttt = test.bar() private val qqq = ttt.qux() -} \ No newline at end of file +} + +interface I +interface I2 + +private fun f(x: V) = object : I> {} +private fun f1(x: V) = object : I> {} +private fun f2(x: V) = object : I2 {} +private fun f3(x: V, y: W) = object : I> {} + +fun g() = f("f") +fun g1() = f("f1") +fun g2() = f2("f2") +fun g3() = f3("f3", 3) diff --git a/compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.txt b/compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.txt index 2aac0385567..e928a799b63 100644 --- a/compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.txt +++ b/compiler/testData/diagnostics/tests/inference/substitutions/hideLocalTypeForReturnTypeOfSingleExpressionFunction.txt @@ -1,7 +1,15 @@ package +private fun f(/*0*/ x: V): f.`` +private fun f1(/*0*/ x: V): f1.`` +private fun f2(/*0*/ x: V): f2.`` +private fun f3(/*0*/ x: V, /*1*/ y: W): f3.`` private fun fPrivate(): test.`` public fun fPublic(): A +public fun g(): I> +public fun g1(): I> +public fun g2(): I2 +public fun g3(): I> public fun main(): kotlin.Unit private fun test(/*0*/ t: T): test.`` @@ -23,3 +31,15 @@ public final class FieldTest { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } +public interface I { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface I2 { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} +