From dbca7358af79ac75f49e980cc25d65ec1cca1e63 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 11 Dec 2023 18:13:06 +0100 Subject: [PATCH] K2: add explicit cast to Any for Any function calls on stub types This commit solves a stub type inconsistency problem. As a part of KT-59369 fix we decided (see commit 299d2799), that ConeStubTypeForChainInference has a scope of Any, so we can safely resolve only to equals/hashCode/toString. However, later we can replace a stub type with some inferred type, which can have its own equals/hashCode/toString implementation, while the call still refers Any member. In this situation FIR2IR decides that we are calling a fake override, which is not true, in fact we are calling an overriding method. This leads to a crash in Native backend. To solve this situation, we provide an explicit cast of a dispatch receiver with a stub type (ConeStubTypeForChainInference) to Any, thus confirming directly we are calling Any method and nothing else. #KT-63932 Fixed --- ...CompilerTestFE10TestdataTestGenerated.java | 12 +++++ ...sticCompilerFE10TestDataTestGenerated.java | 12 +++++ ...eeOldFrontendDiagnosticsTestGenerated.java | 12 +++++ ...siOldFrontendDiagnosticsTestGenerated.java | 12 +++++ .../fir/resolve/calls/tower/TowerLevels.kt | 13 ++++++ .../org/jetbrains/kotlin/KtSourceElement.kt | 3 ++ ...teStubTypeIntolambdaParameterDescriptor.kt | 1 - .../coroutines/inference/kt36220.fir.txt | 2 +- .../inference/stubCallOnReceiver.fir.txt | 44 +++++++++++++++++++ .../inference/stubCallOnReceiver.kt | 24 ++++++++++ .../inference/stubCallOnVariable.fir.txt | 32 ++++++++++++++ .../inference/stubCallOnVariable.kt | 19 ++++++++ .../test/runners/DiagnosticTestGenerated.java | 12 +++++ 13 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnReceiver.fir.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnReceiver.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnVariable.fir.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnVariable.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index 5e53d8ae3b8..fb595b791bd 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -43265,6 +43265,18 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/simpleGenerator.kt"); } + @Test + @TestMetadata("stubCallOnReceiver.kt") + public void testStubCallOnReceiver() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnReceiver.kt"); + } + + @Test + @TestMetadata("stubCallOnVariable.kt") + public void testStubCallOnVariable() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnVariable.kt"); + } + @Test @TestMetadata("suspendCallsWithErrors.kt") public void testSuspendCallsWithErrors() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index b4162e4db1a..3d8a71c4421 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -43265,6 +43265,18 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/simpleGenerator.kt"); } + @Test + @TestMetadata("stubCallOnReceiver.kt") + public void testStubCallOnReceiver() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnReceiver.kt"); + } + + @Test + @TestMetadata("stubCallOnVariable.kt") + public void testStubCallOnVariable() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnVariable.kt"); + } + @Test @TestMetadata("suspendCallsWithErrors.kt") public void testSuspendCallsWithErrors() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index a585ad6e588..e195866b846 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -41067,6 +41067,18 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/simpleGenerator.kt"); } + @Test + @TestMetadata("stubCallOnReceiver.kt") + public void testStubCallOnReceiver() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnReceiver.kt"); + } + + @Test + @TestMetadata("stubCallOnVariable.kt") + public void testStubCallOnVariable() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnVariable.kt"); + } + @Test @TestMetadata("suspendCallsWithErrors.kt") public void testSuspendCallsWithErrors() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index a0d575e5135..1f282271bbf 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -41187,6 +41187,18 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/simpleGenerator.kt"); } + @Test + @TestMetadata("stubCallOnReceiver.kt") + public void testStubCallOnReceiver() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnReceiver.kt"); + } + + @Test + @TestMetadata("stubCallOnVariable.kt") + public void testStubCallOnVariable() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnVariable.kt"); + } + @Test @TestMetadata("suspendCallsWithErrors.kt") public void testSuspendCallsWithErrors() throws Exception { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt index 6206b57e272..7e08bf42525 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/tower/TowerLevels.kt @@ -13,8 +13,11 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.isInner import org.jetbrains.kotlin.fir.declarations.utils.isStatic import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.expressions.FirOperation import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression +import org.jetbrains.kotlin.fir.expressions.buildUnaryArgumentList import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier +import org.jetbrains.kotlin.fir.expressions.builder.buildTypeOperatorCall import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.* import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider @@ -25,6 +28,7 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.impl.FirImplicitAnyTypeRef import org.jetbrains.kotlin.fir.utils.exceptions.withConeTypeEntry import org.jetbrains.kotlin.name.StandardClassIds.Annotations.HidesMembers import org.jetbrains.kotlin.types.AbstractTypeChecker @@ -213,6 +217,15 @@ class MemberScopeTowerLevel( val dispatchReceiverToUse = when { isFromOriginalTypeInPresenceOfSmartCast -> getOriginalReceiverExpressionIfStableSmartCast() + // For a chain inference stub in dispatch receiver, we have to provide an explicit cast to Any + // See KT-63932 + dispatchReceiverValue.type is ConeStubTypeForChainInference -> buildTypeOperatorCall { + source = dispatchReceiverValue.receiverExpression.source?.fakeElement(KtFakeSourceElementKind.CastToAnyForStubTypes) + operation = FirOperation.AS + conversionTypeRef = FirImplicitAnyTypeRef(source) + argumentList = buildUnaryArgumentList(dispatchReceiverValue.receiverExpression) + coneTypeOrNull = session.builtinTypes.anyType.coneType + } else -> dispatchReceiverValue.receiverExpression } diff --git a/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt b/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt index adf7df10e9f..26957e7da65 100644 --- a/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt +++ b/compiler/frontend.common/src/org/jetbrains/kotlin/KtSourceElement.kt @@ -291,6 +291,9 @@ sealed class KtFakeSourceElementKind(final override val shouldSkipErrorTypeRepor // When a lambda is converted to a SAM type, the expression is wrapped in an extra node object SamConversion : KtFakeSourceElementKind() + + // For it.functionFromAny() calls on a stub type + object CastToAnyForStubTypes : KtFakeSourceElementKind() } sealed class AbstractKtSourceElement { diff --git a/compiler/testData/codegen/box/inference/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt b/compiler/testData/codegen/box/inference/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt index 71580ab7b61..f877f5014d0 100644 --- a/compiler/testData/codegen/box/inference/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt +++ b/compiler/testData/codegen/box/inference/builderInference/substituteStubTypeIntolambdaParameterDescriptor.kt @@ -1,5 +1,4 @@ // WITH_STDLIB -// IGNORE_BACKEND_K2: NATIVE import kotlin.experimental.ExperimentalTypeInference diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/kt36220.fir.txt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/kt36220.fir.txt index 722732b73c6..cf2b0a023c3 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/kt36220.fir.txt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/kt36220.fir.txt @@ -23,7 +23,7 @@ FILE: kt36220.kt } ) this@R|special/anonymous|.R|SubstitutionOverride|( = serialize@fun (it: R|kotlin/Int|): R|kotlin/Any?| { - ^ R|/it|.R|kotlin/Any.toString|() + ^ (R|/it| as R|kotlin/Any|).R|kotlin/Any.toString|() } ) } diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnReceiver.fir.txt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnReceiver.fir.txt new file mode 100644 index 00000000000..e910defc009 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnReceiver.fir.txt @@ -0,0 +1,44 @@ +FILE: stubCallOnReceiver.kt + public final class TypeDefinition : R|kotlin/Any| { + public constructor(): R|TypeDefinition| { + super() + } + + public final fun parse(parser: R|(@R|kotlin/ParameterName|(name = String(serializedValue)) kotlin/String) -> KotlinType?|): R|kotlin/Unit| { + ^parse R|kotlin/TODO|() + } + + public final fun serialize(parser: R|KotlinType.() -> kotlin/Any?|): R|kotlin/Unit| { + ^serialize R|kotlin/TODO|() + } + + } + public final fun defineType(definition: R|TypeDefinition.() -> kotlin/Unit|): R|kotlin/Unit| { + ^defineType R|kotlin/TODO|() + } + public final fun foo(): R|kotlin/Unit| { + R|/defineType|( = defineType@fun R|TypeDefinition|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|SubstitutionOverride|( = parse@fun (it: R|@R|kotlin/ParameterName|(name = String(serializedValue)) kotlin/String|): R|kotlin/Int?| { + ^ R|/it|.R|kotlin/text/toInt|() + } + ) + this@R|special/anonymous|.R|SubstitutionOverride|( = serialize@fun R|kotlin/Int|.(): R|kotlin/Any?| { + ^ (this@R|special/anonymous| as R|kotlin/Any|).R|kotlin/Any.toString|() + } + ) + } + ) + } + public final fun bar(): R|kotlin/Unit| { + R|/defineType|( = defineType@fun R|TypeDefinition|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|SubstitutionOverride|( = parse@fun (it: R|@R|kotlin/ParameterName|(name = String(serializedValue)) kotlin/String|): R|kotlin/Int?| { + ^ R|/it|.R|kotlin/text/toInt|() + } + ) + this@R|special/anonymous|.R|SubstitutionOverride|( = serialize@fun R|kotlin/Int|.(): R|kotlin/Any?| { + ^ (this@R|special/anonymous| as R|kotlin/Any|).R|kotlin/Any.toString|() + } + ) + } + ) + } diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnReceiver.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnReceiver.kt new file mode 100644 index 00000000000..0c214d8dbaa --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnReceiver.kt @@ -0,0 +1,24 @@ +// FIR_IDENTICAL +// FIR_DUMP +// Similar to kt36220.kt, but with receivers instead of it + +class TypeDefinition { + fun parse(parser: (serializedValue: String) -> KotlinType?): Unit = TODO() + fun serialize(parser: KotlinType.() -> Any?): Unit = TODO() +} + +fun defineType(definition: TypeDefinition.() -> Unit): Unit = TODO() + +fun foo() { + defineType { + parse { it.toInt() } + serialize { toString() } + } +} + +fun bar() { + defineType { + parse { it.toInt() } + serialize { this.toString() } + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnVariable.fir.txt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnVariable.fir.txt new file mode 100644 index 00000000000..2d1370151d6 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnVariable.fir.txt @@ -0,0 +1,32 @@ +FILE: stubCallOnVariable.kt + public final class TypeDefinition : R|kotlin/Any| { + public constructor(): R|TypeDefinition| { + super() + } + + public final fun parse(parser: R|(@R|kotlin/ParameterName|(name = String(serializedValue)) kotlin/String) -> KotlinType?|): R|kotlin/Unit| { + ^parse R|kotlin/TODO|() + } + + public final fun serialize(parser: R|(@R|kotlin/ParameterName|(name = String(value)) KotlinType) -> kotlin/Any?|): R|kotlin/Unit| { + ^serialize R|kotlin/TODO|() + } + + } + public final fun defineType(definition: R|TypeDefinition.() -> kotlin/Unit|): R|kotlin/Unit| { + ^defineType R|kotlin/TODO|() + } + public final fun main(): R|kotlin/Unit| { + R|/defineType|( = defineType@fun R|TypeDefinition|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|SubstitutionOverride|( = parse@fun (it: R|@R|kotlin/ParameterName|(name = String(serializedValue)) kotlin/String|): R|kotlin/Int?| { + ^ R|/it|.R|kotlin/text/toInt|() + } + ) + this@R|special/anonymous|.R|SubstitutionOverride|( = serialize@fun (it: R|kotlin/Int|): R|kotlin/Any?| { + lval i: R|kotlin/Int| = R|/it| + ^ (R|/i| as R|kotlin/Any|).R|kotlin/Any.toString|() + } + ) + } + ) + } diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnVariable.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnVariable.kt new file mode 100644 index 00000000000..1c34ac142b0 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnVariable.kt @@ -0,0 +1,19 @@ +// FIR_IDENTICAL +// FIR_DUMP + +class TypeDefinition { + fun parse(parser: (serializedValue: String) -> KotlinType?): Unit = TODO() + fun serialize(parser: (value: KotlinType) -> Any?): Unit = TODO() +} + +fun defineType(definition: TypeDefinition.() -> Unit): Unit = TODO() + +fun main() { + defineType { + parse { it.toInt() } + serialize { + val i = it + i.toString() + } + } +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 3a728c97670..45a76c8f7b9 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -43265,6 +43265,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/simpleGenerator.kt"); } + @Test + @TestMetadata("stubCallOnReceiver.kt") + public void testStubCallOnReceiver() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnReceiver.kt"); + } + + @Test + @TestMetadata("stubCallOnVariable.kt") + public void testStubCallOnVariable() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/stubCallOnVariable.kt"); + } + @Test @TestMetadata("suspendCallsWithErrors.kt") public void testSuspendCallsWithErrors() throws Exception {